`
dreamoftch
  • 浏览: 498490 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

HttpURLConnection servlet 多文件参数 断点上传

阅读更多

断点上传 水平较菜 ,多包涵

完善之后的代码:(不再通过发起多次url请求来分段上传,而是仅仅一次请求)

客户端:

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import com.lubansoft.test.upload.po.UploadRecord;
import com.lubansoft.test.upload.utils.ConfigFileUtils;

public class SimpleUrlConnection {
	public static void main(String[] args) {
		SimpleUrlConnection suc =  new SimpleUrlConnection();
		suc.executeuUpload();

		/*if(args != null && args.length > 0){
			String path = args[0];
			path = path.substring("uploadhelper://".length(), path.length());
			args[0] = path;
			getUploadRecord(args);
			SimpleUrlConnection suc =  new SimpleUrlConnection(args[0]);
			suc.executeuUpload();
		}else{
			if(!RegistryUtils.isRegistered()){
				RegistryUtils.register();
			}
		}*/
	
	}
	private HttpURLConnection conn;
	boolean isShowRate = false;
	int streamLength = 10240;
	private String[] fileNames;
	private Map<String,String> params;
	
	private UploadRecord[] uploadRecords;
	
	public SimpleUrlConnection(){
	}
	public SimpleUrlConnection(String[] pathNames){
		this.fileNames = pathNames;
	}
	
	//上传文件
	private void executeuUpload() {
		//设定参数
		params = new HashMap<String, String>();
		params.put("key1", "value1");
		params.put("key2", "value2");
		params.put("key3", "value3");
		this.fileNames= new String[]{"E:\\我的文档\\下载\\apache-tomcat-6.0.36-src.zip","E:\\我的文档\\下载\\apache-tomcat-6.0.36-windows-x86.zip",
				"E:\\我的文档\\下载\\china-code.net.zhy.201238211546823200.Rar"};
//		this.fileNames= new String[]{"E:\\我的文档\\下载\\commons-email-1.3.1-bin.tar.gz"};
//		this.fileNames= new String[]{"E:\\我的文档\\下载\\commons-email-1.3.1-bin.tar.gz","E:\\我的文档\\下载\\commons-email-1.3.1-src.tar.gz"};
//		this.fileNames= new String[]{"E:\\我的文档\\下载\\apache-tomcat-6.0.36-src.zip","E:\\我的文档\\下载\\apache-tomcat-6.0.36-windows-x86.zip"};
		/**
		 * 上传文件之前先获取所有文件上传记录
		 */
		uploadRecords  = getUploadRecord(fileNames);
		/**
		 * 上传文件
		 */
		upload(params,uploadRecords, fileNames);
	}
	
	/**
	 * 
	 *  Created on 2013-5-13 
	 * <p>Discription:查询文件上传记录</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return UploadRecord[]
	 */
	public UploadRecord[] getUploadRecord(String[] fileNames){
		UploadRecord[] records = null;
		if(fileNames == null || fileNames.length<=0){
			return null;
		}
		records = new UploadRecord[fileNames.length];
		OutputStream out = null;
		InputStream in = null;
		File f = null;
		try {
			URL url = new URL("http://localhost:8080/upload/getUploadHistory");
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			out = conn.getOutputStream();
			StringBuilder sb = new StringBuilder();
			int length = fileNames.length;
			for(int i=0;i<length;i++){
				f = new File(fileNames[i]);
				sb.append("fileName="+f.getName()+"&fileSize="+f.length());
				if(i == length-1){
					sb.append("\n");
				}else{
					sb.append(";");
				}
			}
			String request = sb.substring(0, sb.length()-1);
			out.write(request.getBytes("utf-8"));
			out.flush();
			
			in = conn.getInputStream();
			String line = null;
			for(int i=0;i<fileNames.length;i++){
				line = ConfigFileUtils.readLine(in);
				records[i] = getUploadRecoreFromString(line);
			}
			isShowRate = true;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try {
				if(in != null){
					in.close();
					in = null;
				}
				if(out != null){
					out.close();
					out = null;
				}
				f = null;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return records;
	}
	
	/**
	 * 
	 *  Created on 2013-5-13 
	 * <p>Discription:从字符串中提取出UploadRecord对象 :</p>
	 * <p>"fileName="+f.getName()+"&fileSize="+f.length()+"&uploadSize="f.getUploadSize()</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return UploadRecord
	 */
	private UploadRecord getUploadRecoreFromString(String line) {
		return ConfigFileUtils.getUploadRecoreFromString(line);
	}

	/**
	 * 
	 *  Created on 2013-5-13 
	 * <p>Discription:根据服务器返回的UploadRecord[] uploadRecords,开始从断点处上传</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return void
	 */
	public void upload(Map<String,String> params,UploadRecord[] uploadRecords,String[] paths){
		RandomAccessFile in = null;
		File file = null;
		try {
			String url = "http://localhost:8080/upload/uploadServlet";
			URL u = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) u.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			//指定流的大小,当内容达到这个值的时候就把流输出
			conn.setChunkedStreamingMode(1024*1024);
			OutputStream out = conn.getOutputStream();
			if(params != null){
				StringBuilder sb = new StringBuilder();
				for(Map.Entry<String, String> entry:params.entrySet()){
					sb.append(entry.getKey() + "=" + entry.getValue() + "&");
				}
				String param = sb.substring(0, sb.length()-1);
				/**
				 * 首先告诉服务器要传输的是参数
				 */
				out.write("--parameters--\n".getBytes("utf-8"));
				out.write(param.getBytes("utf-8"));
				out.write("\n".getBytes("utf-8"));
			}
			if(uploadRecords != null && uploadRecords.length>0){
				/**
				 * 接下来告诉服务器传递的是文件
				 */
				UploadRecord uploadRecord = null;
				/**
				 * 通过for循环来上传多个文件,每个文件的上传过程为:
				 * 第一行:--file begin--
				 * 第二行:fileName=ddd&fileSize=xxx&uploadSize=aaa
				 * 第三行:开始上传文件内容
				 */
				for(int i=0;i<uploadRecords.length;i++){
					uploadRecord = uploadRecords[i];
					if(uploadRecord.getFileSize() <= uploadRecord.getUploadSize()){
						continue;
					}
					out.write("--file begin--\n".getBytes("utf-8"));
					out.write(("fileName="+uploadRecord.getFileName()+"&fileSize="+uploadRecord.getFileSize()+"&uploadSize="+uploadRecord.getUploadSize()).getBytes("utf-8"));
					out.write("\n".getBytes("utf-8"));
					file = new File(paths[i]);
					in = new RandomAccessFile(file, "r");
					byte[] b = null;
					int n = -1;
					/**
					 * 将指针移动到断点位置
					 */
					in.seek(uploadRecords[i].getUploadSize());
					b = new byte[2048];
					/**
					 * 上传文件内容
					 */
					while ((n = in.read(b)) != -1) {
						out.write(b, 0, n);
					}
					out.flush();
					in.close();
				}
			}
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				System.out.println(line);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				in = null;
			}
			if(file != null){
				file = null;
			}
		}
	}
}

服务器端servlet:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.lubansoft.test.upload.po.UploadRatePercent;
import com.lubansoft.test.upload.po.UploadRecord;
import com.lubansoft.test.upload.utils.ConfigFileUtils;

//文件上传的servlet
public class FixedFileUpload extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private int blockSize ;
	private MathContext mc_rate = new MathContext(4, RoundingMode.HALF_DOWN);
	private MathContext mc_percent = new MathContext(4, RoundingMode.HALF_DOWN);

	public FixedFileUpload() {
		try {
			Properties prop = new Properties();
			prop.load(this.getClass().getResourceAsStream("/blockSize.properties"));
			blockSize = Integer.parseInt(prop.getProperty("blockSize"));
			if(blockSize == 0){
				blockSize = 20480;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			InputStream in = new BufferedInputStream(request.getInputStream(),10240);
			String requestHeader = readLine(in);
			String line = null;
			/**
			 * 判断是否是文件/参数
			 */
			if("--parameters--".equals(requestHeader)){
				Map<String,String> param = new HashMap<String, String>();
				line = readLine(in);
				if(line != null){
					String[] params = line.split("&");
					if(params!=null && params.length>0){
						for(String keyValue : params){
							param.put(keyValue.split("=")[0], keyValue.split("=")[1]);
						}
					}
				}
				System.out.println(param);
				if("--file begin--".equals(line=readLine(in))){
					Timer timer = new Timer();
					UploadRateTimerTask task = new UploadRateTimerTask(request);
					//指定每隔0.5s执行一次定时器
					timer.schedule(task, 0 , 500);
					saveFile(in, request, task);
					//取消定时器
					timer.cancel();
				}
			}else if("--file begin--".equals(requestHeader)){
				Timer timer = new Timer();
				UploadRateTimerTask task = new UploadRateTimerTask(request);
				//指定每隔0.5s执行一次定时器
				timer.schedule(task, 0 , 500);
				saveFile(in, request, task);
				//取消定时器
				timer.cancel();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
	}
	
	
	private String readLine(InputStream in) {
		return ConfigFileUtils.readLine(in);
	}


	//用于显示上传速度和百分比
	class UploadRateTimerTask extends TimerTask{
		private long pre_uploadSize = 0,total_uploadSize = 0;
		UploadRatePercent uploadRatePercent = new UploadRatePercent();
		UploadRecord uploadRecord;
		double rate = 0 ,uploadPercent = 0;
		private HttpServletRequest request;
		
		public UploadRateTimerTask(HttpServletRequest request){
			this.request = request; 
		}
		
		@Override
		public void run() {
			if(pre_uploadSize <= total_uploadSize && uploadRecord != null){
				//rate=2*(当前上传的大小 - 上一时刻上传的大小)/1024      k/s
				//uploadPercent = 100*(当前上传文件的大小/文件总的大小)    %
				rate = new BigDecimal(total_uploadSize+"").subtract(new BigDecimal(pre_uploadSize+"")).multiply(new BigDecimal(2+""))
								.divide(new BigDecimal(1024+""),mc_rate).doubleValue();
				uploadPercent = new BigDecimal(100+"").multiply(new BigDecimal(uploadRecord.getUploadSize()+total_uploadSize+""))
								.divide(new BigDecimal(uploadRecord.getFileSize()+""),mc_percent).doubleValue();
				System.out.println("fileName:  " + uploadRecord.getFileName() + "   " + rate+" k/s   " + uploadPercent +" %");
				uploadRatePercent.setPercent(uploadPercent);
				uploadRatePercent.setRate(rate);
				ConfigFileUtils.updateRateInfoFile(request, uploadRecord.getFileName(), uploadRatePercent);
				pre_uploadSize = total_uploadSize;
			}else{
				pre_uploadSize = total_uploadSize;
			}
		}
		
		public void setTaskComplete(){
			if(pre_uploadSize <= total_uploadSize && uploadRecord != null){
				//rate=2*(当前上传的大小 - 上一时刻上传的大小)/1024      k/s
				//uploadPercent = 100*(当前上传文件的大小/文件总的大小)    %
				rate = 0;
				uploadPercent = new BigDecimal(100+"").multiply(new BigDecimal(uploadRecord.getUploadSize()+total_uploadSize+""))
								.divide(new BigDecimal(uploadRecord.getFileSize()+""),mc_percent).doubleValue();
				System.out.println("fileName:  " + uploadRecord.getFileName() + "   " + rate+" k/s   " + uploadPercent +" %");
				uploadRatePercent.setPercent(uploadPercent);
				uploadRatePercent.setRate(rate);
				ConfigFileUtils.updateRateInfoFile(request, uploadRecord.getFileName(), uploadRatePercent);
				pre_uploadSize = total_uploadSize;
			}
		}
		
		public void setUploadRecord(UploadRecord uploadRecord){
			this.uploadRecord = uploadRecord;
		}
		public UploadRecord getUploadRecord(){
			return uploadRecord;
		}

		public long getTotal_uploadSize() {
			return total_uploadSize;
		}

		public void setTotal_uploadSize(long totalUploadSize) {
			total_uploadSize = totalUploadSize;
		}
	}
	//保存文件
	public void saveFile(InputStream in ,HttpServletRequest request,UploadRateTimerTask task){
		String line=null;
		String fileName=null;
		String fileSize = null;
		String uploadSize=null;
		RandomAccessFile raf = null;
		UploadRecord uploadRecord = null;
		try {
			task.setTotal_uploadSize(0);
			//先读到该文件的信息头“fileName=ddd&fileSize=xxx&uploadSize=aaa”
			line = readLine(in);
			if(line != null){
				String[] info = line.split("&");
				if(info != null && info.length>0){
					for(String s: info){
						if("fileName".equals(s.split("=")[0])){
							fileName = s.split("=")[1];
						}else if("fileSize".equals(s.split("=")[0])){
							fileSize = s.split("=")[1];
						}else if("uploadSize".equals(s.split("=")[0])){
							uploadSize = s.split("=")[1];
						}
					}
					HttpSession session = request.getSession();
					String folder = session.getServletContext().getRealPath("/uploadFiles"); 
					String filepath = folder+File.separator + fileName;
					File file = new File(filepath);
					if(! file.getParentFile().exists()){
						file.getParentFile().mkdirs();
					}
					if(! file.exists()){
						file.createNewFile();
					}
					String config_path = session.getServletContext().getRealPath("/uploadConfig") + File.separator + request.getRemoteAddr() + "-" + fileName + ".properties";
					File config_file = new File(config_path);
					if(! config_file.getParentFile().exists()){
						config_file.getParentFile().mkdirs();
					}
					if (! config_file.exists()) {
						config_file.createNewFile();
					}
					raf = new RandomAccessFile(file, "rwd");
					if(file.length() != Long.parseLong(fileSize)){
						raf.setLength(Long.parseLong(fileSize));
					}
					//将读取文件的指针移动到断点位置
					raf.seek(Long.parseLong(uploadSize));
					//计算出从断点位置到文件结尾,还剩下的文件大小
					long leftSize = Long.parseLong(fileSize)-Long.parseLong(uploadSize);
					//本次上传,上传完成的文件大小
					long completeSize = 0l;
					/**
					 * 接下来是文件的内容
					 */
					int n=-1;
					byte[] b = new byte[2048];
					int total = 0;
					int addSize = 0;
					uploadRecord = new UploadRecord();
					uploadRecord.setFileName(fileName);
					uploadRecord.setFileSize(Long.parseLong(fileSize));
					uploadRecord.setIp(request.getRemoteAddr());
					uploadRecord.setUploadSize(Long.parseLong(uploadSize));
					/**
					 * 在上传文件的时候,再去判断一下是否已经有程序在上传该文件
					 * 作为确认,防止万一
					 */
					boolean isStarted = false;
					if(ConfigFileUtils.isUploadStarted(request, fileName)){
						isStarted = true;
					}
					/**
					 * 为定时器动态绑定uploadRecord对象
					 */
					task.setUploadRecord(uploadRecord);
					/**
					 * 判断文件从断点开始,还有多大文件需要传输,如果太小(小于 1 k )就要特殊处理
					 * 因为这时候不能使用 in.read(b) ,而只能使用 in.read(b,0,leftSize)
					 */
					if((completeSize + b.length) <= leftSize){
						while((n=in.read(b)) != -1){
							raf.write(b,0,n);
							total += n;
							completeSize += n;
							addSize += n;
							task.setTotal_uploadSize(completeSize);
							if(addSize >= blockSize){
								ConfigFileUtils.updateUploadSize(request, uploadRecord, addSize);
								addSize = 0;
							}
							//判断是否已经到达最后一部分
							if((completeSize + b.length) >= leftSize){
								n = (int)(leftSize-completeSize);
								in.read(b, 0, n);
								raf.write(b,0,n);
								total += n;
								completeSize += n;
								addSize += n;
								raf.close();
								task.setTotal_uploadSize(completeSize);
								ConfigFileUtils.updateUploadSize(request, uploadRecord, addSize);
								addSize = 0;
								//完成一个文件的上传,将该文件的完成百分比改为100%
								task.setTaskComplete();
								//完成一个文件的上传,将该文件的isStopped改为stopped
								ConfigFileUtils.setConfigFileStoped(request, uploadRecord);
								line = readLine(in);
								if("--file begin--".equals(line)){
									saveFile(in, request,task);
								}
								break;
							}
						}
					}else{//判断文件从断点开始,如果剩余文件太小(小于 1 k )就要特殊处理
						in.read(b, 0, (int)leftSize);
						if(!isStarted){
							raf.write(b, 0, (int)leftSize);
						}
						raf.close();
						task.setTotal_uploadSize(leftSize);
						ConfigFileUtils.updateUploadSize(request, uploadRecord, leftSize);
						//完成一个文件的上传,将该文件的完成百分比改为100%
						task.setTaskComplete();
						//完成一个文件的上传,将该文件的isStopped改为stopped
						ConfigFileUtils.setConfigFileStoped(request, uploadRecord);
						line = readLine(in);
						if("--file begin--".equals(line)){
							saveFile(in, request,task);
						}
					}
					/**
					 * 文件上传完成,将状态修改为 “stoped”
					 */
					if(uploadRecord != null){
						ConfigFileUtils.setConfigFileStoped(request, uploadRecord);
					}
				}
			}
		} catch (IOException e) {
			/**
			 * 上传过程中出现异常,将状态修改为 “stoped”
			 */
			e.printStackTrace();
		}finally{
			/**
			 * 上传过程中出现异常,将状态修改为 “stoped”
			 */
			if(uploadRecord != null){
				ConfigFileUtils.setConfigFileStoped(request, uploadRecord);
			}
			if(raf != null){
				try {
					raf.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				raf = null;
			}
		}
	}
}

 最大的不同是:1:conn.setChunkedStreamingMode(1024*1024);

//取得序列化对象的大小

或者2:

                       /*ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(record);

oos.flush();

//流的大小为文件大小 + 序列化对象大小 - 已上传的文件大小

int stream_size = (int)(file.length()+bos.size()-begin);

conn.setFixedLengthStreamingMode(stream_size);*/ 

以上两种方法都可以实现获取真正的输出流,而不是缓冲到本地,等getInputstream的时候才输出,这样就不会出现大文件时,内存溢出的情况了

 

 

 查询断点记录servlet:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.lubansoft.test.upload.po.UploadRecord;
import com.lubansoft.test.upload.utils.ConfigFileUtils;

//查询文件上传历史记录的servlet
public class GetUploadHistory extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private int blockSize ;

	public GetUploadHistory(){
		try {
			Properties prop = new Properties();
			prop.load(this.getClass().getResourceAsStream("/blockSize.properties"));
			blockSize = Integer.parseInt(prop.getProperty("blockSize"));
			if(blockSize == 0){
				blockSize = 20480;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Properties prop = null;
		OutputStream out = null;
		InputStream is = null;
		File dir = null;
		File file = null;
		try {
			InputStream in = request.getInputStream();
			String line = ConfigFileUtils.readLine(in);
			if(line == null){
				return;
			}
			String[] keyValues = line.split(";");
			if(keyValues == null || keyValues.length<=0){
				return;
			}
			int length = keyValues.length;
			//先拿到要查询的文件名
			UploadRecord[] uploadRecords =  new UploadRecord[length];
			for(int i=0;i<length;i++){
				uploadRecords[i] = ConfigFileUtils.getUploadRecoreFromString(keyValues[i]);
			}
			UploadRecord r = null;
			if(uploadRecords != null && uploadRecords.length>0){
				for(int i=0;i<uploadRecords.length;i++){
					r = uploadRecords[i];
					prop = new Properties();
					r.setIp(request.getRemoteAddr());
					HttpSession session = request.getSession();
					//指定配置文件的文件夹
					String serverPath = session.getServletContext().getRealPath(
							"/uploadConfig");
					dir = new File(serverPath);
					if (!dir.exists()) {
						dir.mkdirs();
					}
					//指定配置文件名
					String path = serverPath + File.separator + r.getIp() + "-" + r.getFileName()
							 + ".properties";
					file = new File(path);
					if (!file.exists()) {
						file.createNewFile();
					}
					is = new FileInputStream(file);
					prop.load(is);
					String uploadSize = prop.getProperty("uploadSize") == null ? 0+"" : prop.getProperty("uploadSize");
					String fileName = prop.getProperty("fileName") == null ? r.getFileName() : prop.getProperty("fileName");
					String fileSize = prop.getProperty("fileSize") == null ? r.getFileSize()+"" : prop.getProperty("fileSize");
					String isStarted = prop.getProperty("isStarted") == null ? "false" : prop.getProperty("isStarted");
					String ip = request.getRemoteAddr();
					
					prop.setProperty("uploadSize", uploadSize);
					prop.setProperty("fileName", fileName);
					prop.setProperty("fileSize", fileSize);
					prop.setProperty("ip", ip);
					prop.setProperty("isStarted", isStarted);
					
					out = new FileOutputStream(file);
					prop.store(out, "comments");
					out.flush();
					out.close();
					out = null;
					
					r.setUploadSize(Long.parseLong(uploadSize));
					r.setFileName(fileName);
					r.setFileSize(Long.parseLong(fileSize));
					r.setIp(ip);
					r.setIsStarted(isStarted);
					uploadRecords[i] = r;
				}
			}
			StringBuilder sb = new StringBuilder();
			for(int i=0;i<length;i++){
				sb.append("fileName="+uploadRecords[i].getFileName()+"&fileSize="+uploadRecords[i].getFileSize()+"&uploadSize="+uploadRecords[i].getUploadSize());
				if(i != length){
					sb.append("\n");
				}
			}
			OutputStream outputStream = response.getOutputStream();
			outputStream.write(sb.toString().getBytes("utf-8"));
			outputStream.flush();
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(out != null){
				out.flush();
				out.close();
				out = null;
			}
			if(is != null){
				is.close();
				is = null;
			}
			if(prop != null){
				prop.clear();
				prop = null;
			}
			if(dir != null){
				dir = null;
			}
			if(file != null){
				file = null;
			}
		}
	}
}

 

查询上传速度和百分比servlet:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lubansoft.test.upload.utils.ConfigFileUtils;

//获取上传速度和百分比的servlet
public class GetUploadRateAndPercent extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String filepath = request.getParameter("filepath");
		if(filepath != null && !"".equals(filepath)){
			String filename = filepath.substring(filepath.lastIndexOf("\\")+1);
			String isStarted = "false";
			if("true".equals(ConfigFileUtils.isUploadStarted(request, filename))){
				isStarted = "true";
			}else if("false".equals(ConfigFileUtils.isUploadStarted(request, filename))){
				isStarted = "false";
			}
			String[] rateAndPercent = ConfigFileUtils.getUploadRate(request,filename);
			/**
			 * 返回给页面一个字符串:
			 * "{fileName:\""+ filename + "\",isStarted:\"" + isStarted + "\",rate:\"" + rateAndPercent[0] +"\",percent:\"" + rateAndPercent[1] +"\"}"
			 */
			String result = "{fileName:\""+ filename + "\",isStarted:\"" + isStarted + "\",rate:\"" + rateAndPercent[0] +"\",percent:\"" + rateAndPercent[1] +"\"}";
			response.setCharacterEncoding("utf-8");
			response.getWriter().write(result);
			response.getWriter().flush();
			response.getWriter().close();
		}
	}
}

  

用到的util:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.lubansoft.test.upload.po.UploadRatePercent;
import com.lubansoft.test.upload.po.UploadRecord;

public class ConfigFileUtils {

	//更新上传文件的上传速度和百分比
	public static void updateRateInfoFile(HttpServletRequest request ,String fileName, UploadRatePercent uploadRatePercent){
		FileInputStream in = null;
		File rateInfoFie = null;
		Properties prop = null;
		try {
			HttpSession session = request.getSession();
			String folder = session.getServletContext().getRealPath("/uploadRate"); 
			String filepath = folder+File.separator+request.getRemoteAddr()+"-"+fileName+"-"+"RateAndPercent.properties";
			rateInfoFie = new File(filepath);
			if(! rateInfoFie.getParentFile().exists()){
				rateInfoFie.getParentFile().mkdirs();
			}
			if(! rateInfoFie.exists()){
				rateInfoFie.createNewFile();
			}
			prop = new Properties();
			in = new FileInputStream(rateInfoFie);
			prop.load(in);
			prop.setProperty("fileName", prop.getProperty("fileName") == null ? fileName : prop.getProperty("fileName"));
			prop.setProperty("rate", uploadRatePercent.getRate()+"");
			prop.setProperty("percent", uploadRatePercent.getPercent()+"");
			FileOutputStream o = new FileOutputStream(rateInfoFie);
			prop.store(o, "comments");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
					in = null;
					rateInfoFie = null;
					prop = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	//更新已经上传文件大小
	public static void updateUploadSize(HttpServletRequest request ,UploadRecord uploadRecord , long addSize) {
		FileInputStream in = null;
		File rateInfoFie = null;
		Properties prop = null;
		try {
			HttpSession session = request.getSession();
			String folder = session.getServletContext().getRealPath("/uploadConfig"); 
			String filepath = folder+File.separator+request.getRemoteAddr()+"-"+uploadRecord.getFileName() + ".properties";
			rateInfoFie = new File(filepath);
			if(! rateInfoFie.getParentFile().exists()){
				rateInfoFie.getParentFile().mkdirs();
			}
			if(! rateInfoFie.exists()){
				rateInfoFie.createNewFile();
			}
			prop = new Properties();
			in = new FileInputStream(rateInfoFie);
			prop.load(in);
			String old_uploadSize = prop.getProperty("uploadSize");
			if(old_uploadSize == null){
				old_uploadSize = "0";
			}
			long uploadSize = Long.parseLong(old_uploadSize);
			prop.setProperty("uploadSize", uploadSize + addSize + "");
			prop.setProperty("isStarted", "true");
			FileOutputStream o = new FileOutputStream(rateInfoFie);
			prop.store(o, "comments");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
					in = null;
					rateInfoFie = null;
					prop = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	//更新该用户该文件的上传状态为“已停止”
	public static void setConfigFileStoped(HttpServletRequest request ,UploadRecord uploadRecord){
		FileInputStream in = null;
		File rateInfoFie = null;
		Properties prop = null;
		try {
			HttpSession session = request.getSession();
			String folder = session.getServletContext().getRealPath("/uploadConfig"); 
			String filepath = folder+File.separator+request.getRemoteAddr()+"-"+uploadRecord.getFileName() + ".properties";
			rateInfoFie = new File(filepath);
			if(! rateInfoFie.getParentFile().exists()){
				rateInfoFie.getParentFile().mkdirs();
			}
			if(! rateInfoFie.exists()){
				rateInfoFie.createNewFile();
			}
			prop = new Properties();
			in = new FileInputStream(rateInfoFie);
			prop.load(in);
			prop.setProperty("isStarted", "false");
			FileOutputStream o = new FileOutputStream(rateInfoFie);
			prop.store(o, "comments");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
					in = null;
					rateInfoFie = null;
					prop = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * 
	 *  Created on 2013-5-10 
	 * <p>Discription:查询上传的速度和百分比</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return String[]
	 */
	public static String[] getUploadRate(HttpServletRequest request ,String fileName){
		FileInputStream in = null;
		File rateInfoFie = null;
		Properties prop = null;
		try {
			HttpSession session = request.getSession();
			String folder = session.getServletContext().getRealPath("/uploadRate");
			String path = folder+File.separator+request.getRemoteAddr()+"-"+fileName+"-"+"RateAndPercent.properties";
			rateInfoFie = new File(path);
			if(! rateInfoFie.getParentFile().exists()){
				rateInfoFie.getParentFile().mkdirs();
			}
			if(! rateInfoFie.exists()){
				rateInfoFie.createNewFile();
			}
			prop = new Properties();
			in = new FileInputStream(rateInfoFie);
			prop.load(in);
			String rate = prop.getProperty("rate") == null ? "0" : prop.getProperty("rate");
			String percent = prop.getProperty("percent") == null ? "0" : prop.getProperty("percent");
			return new String[]{rate,percent};
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
					in = null;
					rateInfoFie = null;
					prop = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return new String[]{"",""};
	}
	/**
	 * 
	 *  Created on 2013-5-10 
	 * <p>Discription:查询该用户 该文件 的上传状态为“已启动”</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return boolean
	 */
	public static boolean isUploadStarted(HttpServletRequest request ,String fileName){
		FileInputStream in = null;
		File rateInfoFie = null;
		Properties prop = null;
		try {
			HttpSession session = request.getSession();
			String folder = session.getServletContext().getRealPath("/uploadConfig"); 
			String filepath = folder+File.separator+request.getRemoteAddr()+"-"+ fileName + ".properties";
			rateInfoFie = new File(filepath);
			if(! rateInfoFie.getParentFile().exists()){
				rateInfoFie.getParentFile().mkdirs();
			}
			if(! rateInfoFie.exists()){
				rateInfoFie.createNewFile();
			}
			prop = new Properties();
			in = new FileInputStream(rateInfoFie);
			prop.load(in);
			if("true".equals(prop.getProperty("isStarted"))){
				return true;
			}else if("false".equals(prop.getProperty("isStarted"))){
				return false;
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
					in = null;
					rateInfoFie = null;
					prop = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
	
	/**
	 * 
	 *  Created on 2013-5-13 
	 * <p>Discription:读取一行内容</p>
	 * @author:田超辉 tianchaohui@dev.com
	 * @update:[日期YYYY-MM-DD] [更改人姓名]
	 * @return String
	 */
	public static String readLine(InputStream in){
		String result = null;
		try {
			byte[] b = new byte[1];
			int n = -1;
			while((n = in.read()) != -1){
				if(n == '\r' || n == '\n'){
					break;
				}else{
					b[b.length-1] = (byte)n;
					b = Arrays.copyOf(b, b.length+1);
				}
			}
			if(b.length <= 1){
				return null;
			}
			b = Arrays.copyOf(b, b.length-1);
			return new String(b,"utf-8");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return result;
	}
	
	/**
	 * 从字符串中提取出UploadRecord对象
	 * "fileName="+f.getName()+"&fileSize="+f.length()+"&uploadSize="f.getUploadSize()
	 */
	public static UploadRecord getUploadRecoreFromString(String line) {
		UploadRecord record = null;
		if(line == null){
			return null;
		}
		String[] keyValues = line.split("&");
		if(keyValues == null || keyValues.length<=0){
			return null;
		}
		record = new UploadRecord();
		int length = keyValues.length;
		for(int i=0;i<length;i++){
			if("fileName".equals(keyValues[i].split("=")[0])){
				record.setFileName(keyValues[i].split("=")[1]);
			}else if("fileSize".equals(keyValues[i].split("=")[0])){
				record.setFileSize(Long.parseLong(keyValues[i].split("=")[1]));
			}else if("uploadSize".equals(keyValues[i].split("=")[0])){
				record.setUploadSize(Long.parseLong(keyValues[i].split("=")[1]));
			}
		}
		return record;
	}
}

 

 

 

优化之前:

 

客户端代码:

package com.lubansoft.test.upload.client;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import com.lubansoft.test.upload.po.UploadRecord;

public class SimpleUrlConnection {
	private HttpURLConnection conn;
	private OutputStream out = null;
	private File file = null;
	private UploadRecord record = null;
	private MathContext mc_rate = new MathContext(4, RoundingMode.HALF_DOWN);
	private MathContext mc_percent = new MathContext(3, RoundingMode.HALF_DOWN);
	private static long total_uploadSize = 0;
	boolean isShowRate = false;
	
	public SimpleUrlConnection(String pathname){
		file = new File(pathname);
	}
	//分块上传begin该块的起点,end该块的终点,blockSize每块的大小
	public void upload(long begin,long end,long blockSize){
		try {
			String url = "http://localhost:8080/upload/uploadServlet";
			URL u = new URL(url);
			conn = (HttpURLConnection) u.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			out = conn.getOutputStream();
			//RandomAccessFile是断点上传的关键(其实也是断点下载的关键),可以从文件任意位置随机读写r,rw,rwd(读写时用),rws
			RandomAccessFile in = new RandomAccessFile(file, "r");
			byte[] b = null;
			int n = -1;
			int total = 0;
			in.seek(begin);
			b = new byte[2048];
			record = new UploadRecord();
			record.setUploadSize(begin);
			record.setFileName(file.getName());
			record.setFileSize(file.length());
			record.setBlockSize(blockSize);
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(record);
			long begin_timemilis = System.currentTimeMillis();
			while ((n = in.read(b)) != -1) {
				total += n;
				if((total+begin)<=end){
					out.write(b, 0, n);
					total_uploadSize += n;
				}else{
					if((total+begin)<(end+b.length)){
						total-=n;
						n=(int) (end-total-begin);
						total+=n;
						out.write(b,0,n);
						total_uploadSize += n;
					}else{
						total-=n;
						break;
					}
				}
			}
			//该http请求真正发送出去的地方conn.getInputStream(),如果不调用该方法,则不发出请求
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
//				System.out.println(line);
			}
//			BigDecimal cost_time = new BigDecimal(System.currentTimeMillis()-begin_timemilis+"").divide(new BigDecimal(1000+""),mc);
//			BigDecimal send_file_size = new BigDecimal(end-begin+"").divide(new BigDecimal(1024+""));
//			double rate = send_file_size.divide(cost_time,mc).doubleValue();
//			System.out.println(rate + " k/s"+ "    所用时间为:"+(System.currentTimeMillis()-begin_timemilis)/1000+"  s  "+"   传输的文件大小为: " +(end-begin)/1024+" k    "+((end-begin)==total)+"   " +
//					" begin: "+begin+" b     end: "+end+" b");
//			double percent = new BigDecimal((total+begin)*100+"").divide(new BigDecimal(record.getFileSize()+""),mc).doubleValue();
//			System.out.println(percent+" %");
		}catch(ArithmeticException e){
			//e.printStackTrace();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		SimpleUrlConnection suc =  new SimpleUrlConnection("E:\\我的文档\\下载\\jetty-6.1.26.zip");
		suc.method();
	}
	//用于显示上传速度和百分比
	class uploadRateTimerTask extends TimerTask{
		private long pre_uploadSize = 0;
		private double rate = 0;
		private double uploadPercent;
		private long fileSize = (file == null ? 0 :file.length());
		@Override
		public void run() {
			if(pre_uploadSize <= total_uploadSize && fileSize != 0 && isShowRate){
				rate = new BigDecimal(total_uploadSize+"").subtract(new BigDecimal(pre_uploadSize+"")).divide(new BigDecimal(1024+""),mc_rate).doubleValue();
//				rate = 2*(total_uploadSize - pre_uploadSize)/1024;
//				uploadPercent = 100.0*total_uploadSize/fileSize;
				uploadPercent = new BigDecimal(100+"").multiply(new BigDecimal(total_uploadSize+"")).divide(new BigDecimal(fileSize+""),mc_percent).doubleValue();
				System.out.println(rate+" k/s   " + uploadPercent +" %");
				pre_uploadSize = total_uploadSize;
			}
		}
	}
	
	private void method() {
		//上传文件之前先获取上传记录
		record  = getUploadRecord();
		Timer timer = new Timer();
		uploadRateTimerTask task = new uploadRateTimerTask();
		//指定每隔0.5s执行一次定时器
		timer.schedule(task, 0 , 500);
		long fileSize = record.getFileSize();
		long uploadSize = record.getUploadSize();
		long blockSize = record.getBlockSize();
		int num = (int) ((fileSize-uploadSize)%blockSize == 0 ? (fileSize-uploadSize)/blockSize : (fileSize-uploadSize)/blockSize + 1);
		long begin=0,end=0;
		//开始分段上传文件(如果以前有上传记录,则从断点处开始上传,从而实现断点上传)
		for(int i = 0;i<num ;i++){
			//uploadSize:已上传的文件大小
			begin = i*blockSize+uploadSize;
			end =((i+1)*blockSize+uploadSize)<=fileSize ? (i+1)*blockSize+uploadSize : fileSize;
			//开始分块上传文件
			upload(begin, end,blockSize);
		}
		System.out.println("100 %");
		//取消定时器
		timer.cancel();
	}
	//获取上传记录
	public UploadRecord getUploadRecord(){
		try {
			URL url = new URL("http://localhost:8080/upload/getUploadHistory");
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			out = conn.getOutputStream();
			record = new UploadRecord();
			record.setFileName(file.getName());
			record.setFileSize(file.length());
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(record);
			ObjectInputStream ois = new ObjectInputStream(conn.getInputStream());
			record = (UploadRecord) ois.readObject();
			isShowRate = true;
			total_uploadSize = record.getUploadSize();
			oos.close();
			ois.close();
			oos=null;
			ois = null;
		}catch(Exception e){
			e.printStackTrace();
		}
		return record;
	}
	
}

 

 

获取上传历史记录的servlet:

package com.lubansoft.test.upload.web.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.lubansoft.test.upload.po.UploadRecord;

//查询文件上传历史记录的servlet
public class GetUploadHistory extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private int blockSize = 204800;//200k

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			InputStream in = request.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(in);
			UploadRecord r = (UploadRecord) ois.readObject();

			Properties prop = new Properties();
			r.setIp(request.getRemoteAddr());
			HttpSession session = request.getSession();
			//指定配置文件的文件夹
			String serverPath = session.getServletContext().getRealPath(
					"/uploadConfig");
			File dir = new File(serverPath);
			if (!dir.exists()) {
				dir.mkdirs();
			}
			//指定配置文件名
			String path = serverPath + "/" + r.getIp() + "-" + r.getFileName()
					+ "-" + r.getFileSize() + ".properties";
			File file = new File(path);
			if (!file.exists()) {
				file.createNewFile();
			}
			prop.load(new FileInputStream(file));
			String uploadSize = prop.getProperty("uploadSize") == null ? 0+"" : prop.getProperty("uploadSize");
			String fileName = prop.getProperty("fileName") == null ? r.getFileName() : prop.getProperty("fileName");
			String fileSize = prop.getProperty("fileSize") == null ? r.getFileSize()+"" : prop.getProperty("fileSize");
			String ip = request.getRemoteAddr();
			
			/*if(uploadSize != null && ! "0".equals(uploadSize) && !uploadSize.equals(fileSize)){
				long uploadSize_value = Long.parseLong(uploadSize);
				uploadSize_value -= blockSize;
				uploadSize = uploadSize_value+"";
			}*/
			
			prop.setProperty("uploadSize", uploadSize);
			prop.setProperty("fileName", fileName);
			prop.setProperty("fileSize", fileSize);
			prop.setProperty("blockSize", blockSize+"");
			prop.setProperty("ip", ip);
			
			r.setUploadSize(Long.parseLong(uploadSize));
			r.setFileName(fileName);
			r.setFileSize(Long.parseLong(fileSize));
			r.setBlockSize(blockSize);
			r.setIp(ip);
			
			OutputStream o = new FileOutputStream(file);
			prop.store(o, "comments");
			o.flush();
			o.close();
			
			ObjectOutputStream oos = new ObjectOutputStream(response.getOutputStream());
			oos.writeObject(r);
			oos.flush();
			oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

文件上传的servlet:

package com.lubansoft.test.upload.web.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.lubansoft.test.upload.po.UploadRecord;

//文件上传的servlet
public class FileUpload extends HttpServlet {
	private static final long serialVersionUID = 1L;
	int i = 0;

	public FileUpload() {
		super();
	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RandomAccessFile randomAccessFile = null;
		Properties prop = null;
		File file = null;
		String path = null;
		String serverPath = null;
		UploadRecord r = null;
		HttpSession session = request.getSession();
		OutputStream o = null;
		boolean isConfigFileChanged = false;
		try {
			InputStream in = request.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(in);
			r = (UploadRecord) ois.readObject();
			//指定保存文件的文件夹
			serverPath = session.getServletContext()
					.getRealPath("/uploadFiles");
			File dir = new File(serverPath);
			if (!dir.exists()) {
				dir.mkdirs();
			}
			//指定保存的文件名
			path = serverPath + "/" + r.getFileName();
			file = new File(path);
			if (!file.exists()) {
				file.createNewFile();
			}
			// 开始位置
			long begin = r.getUploadSize();
			// 随机读写操作rwd
			randomAccessFile = new RandomAccessFile(file, "rwd");
			if (file.length() != r.getFileSize()) {
				randomAccessFile.setLength(r.getFileSize());
			}
			// 指定读写操作的开始位置
			randomAccessFile.seek(begin);
			int n = -1;
			byte[] b = new byte[2048];
			int total = 0;
			while ((n = in.read(b)) != -1) {
				total += n;
				randomAccessFile.write(b, 0, n);
			}
			System.out.println("begin+total:      " + (begin + total)
					+ "      begin: " + begin + "   --  total: " + total
					+ "               --              ------------");
			i += total;
			System.out.println(i);

			prop = new Properties();
			r.setIp(request.getRemoteAddr());
			serverPath = session.getServletContext().getRealPath(
					"/uploadConfig");
			dir = new File(serverPath);
			if (!dir.exists()) {
				dir.mkdirs();
			}
			path = serverPath + "/" + r.getIp() + "-" + r.getFileName() + "-"
					+ r.getFileSize() + ".properties";
			file = new File(path);
			if (!file.exists()) {
				file.createNewFile();
			}
			prop.load(new FileInputStream(file));
			System.out.println(file.getAbsolutePath());
			String uploadSize = prop.getProperty("uploadSize");
			if (uploadSize == null) {
				uploadSize = "0";
			}
			long temp = Long.parseLong(uploadSize) + total;
			prop.setProperty("uploadSize", temp + "");
			//执行到这里的话,如果出了异常,则需要将这次操作回滚
			isConfigFileChanged = true;
			o = new FileOutputStream(file);
			prop.store(o, "comments");
			response.getWriter().write("OK");
		} catch (Exception e) {
			if (r != null && isConfigFileChanged) {
				updateConfigFile(r, request, response);
			}
			e.printStackTrace();
		} finally {
			if (randomAccessFile != null) {
				randomAccessFile.close();
				randomAccessFile = null;
			}
		}
	}
	//出异常的时候,配置文件回滚
	private void updateConfigFile(UploadRecord r, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			Properties prop = new Properties();
			String serverPath = request.getSession().getServletContext()
					.getRealPath("/uploadConfig");
			r.setIp(request.getRemoteAddr());
			String path = serverPath + "/" + r.getIp() + "-" + r.getFileName()
					+ "-" + r.getFileSize() + ".properties";
			File file = new File(path);
			FileInputStream in = new FileInputStream(file);
			prop.load(in);
			if (r != null) {
				prop.setProperty("uploadSize", (r.getUploadSize() - r.getBlockSize()) + "");
				FileOutputStream o = new FileOutputStream(file);
				prop.store(o, "comments");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

	<!-- 查询上传历史记录 -->
  <servlet>
    <servlet-name>UploadServlet</servlet-name>
    <servlet-class>com.lubansoft.test.upload.web.servlet.FileUpload</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>GetUploadHistory</servlet-name>
    <servlet-class>com.lubansoft.test.upload.web.servlet.GetUploadHistory</servlet-class>
  </servlet>

<!-- 文件上传的servlet -->
  <servlet-mapping>
    <servlet-name>UploadServlet</servlet-name>
    <url-pattern>/uploadServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>GetUploadHistory</servlet-name>
    <url-pattern>/getUploadHistory</url-pattern>
  </servlet-mapping>
  
</web-app>

 

jar包,可能有多余的:

  • src.rar (22.4 KB)
  • 下载次数: 32
分享到:
评论

相关推荐

    java 文件上传下载 断点续传 断点上传

    本文将详细介绍如何在Java中实现文件的上传与下载,并重点讨论断点续传和断点上传的技术实现。 首先,让我们从基础开始。在Web端进行文件上传通常涉及到HTML表单、Servlet或Spring MVC等技术。在HTML中,可以使用`...

    实现android开发以servlet方式拍照上传图片到服务器,断点下载

    总结,实现Android应用中的图片上传和断点续传下载涉及多个技术点,包括Android权限管理、Intent交互、网络请求、文件操作、服务器端Servlet配置以及异常处理等。熟练掌握这些技术,能够让你构建出更完善的Android...

    android 选择文件上传至服务器 包含服务器代码

    - 大多数服务器要求文件上传使用`multipart/form-data`格式,因为它可以携带多个部分,包括文件和额外的参数。 - 在Android客户端,可以使用`HttpURLConnection`的`setFixedLengthStreamingMode()`或`...

    android下载服务器(servlet)端文件

    这个项目为你提供了一个基础的Android文件下载系统的实例,你可以根据实际需求对其进行修改和扩展,例如添加断点续传、多线程下载等高级功能。通过理解并实践这些知识点,你将能够更好地理解和构建Android与服务器...

    java上传文件到服务器

    在Web应用程序中,通常使用Servlet API来处理服务器端的文件上传。`HttpServletRequest`对象提供了`getParts()`方法,可以用来获取上传的文件部分。你需要在Servlet中解析这些部分并保存到服务器的文件系统、数据库...

    文件上传源码 客户端服务端

    同时,对于大文件,可能需要采用断点续传,确保在网络不稳定时能够恢复上传。 总之,文件上传是一个涉及客户端与服务器交互的复杂过程,需要理解HTTP协议、文件I/O、网络编程以及可能的云存储服务的API。...

    支持超大文件上传带进度条示例

    1. **分块上传**:由于Java标准库的`Servlet`或`HttpURLConnection`不支持大文件流式上传,因此通常采用分块上传的方式。将大文件分割成小块,逐个上传,这样可以避免一次性加载整个文件到内存中,减少内存压力。 2...

    android上传文件,java服务器接收 客户端与服务器端两端上传代码

    3. **性能优化**:对于大文件上传,考虑分块上传和断点续传,以减少内存占用和提高稳定性。 4. **并发处理**:服务器端需要考虑并发处理多个上传请求的能力。 5. **日志记录**:记录上传日志,便于问题排查和监控...

    java文件的上传与下载

    2. **Servlet**:在传统的 Java Web 应用中,我们通常会使用 Servlet 来处理文件上传和下载。`javax.servlet.http.HttpServletRequest` 可以用来获取上传文件的信息,如文件名、大小等。`javax.servlet....

    文件上传源码集合(爱心奉献)

    9. **UUploader**:UUploader是一个流行的JavaScript文件上传控件,支持多文件选择、断点续传等功能,如`UUploaderBeta60028.EXE`和`UUploaderBeta60028.rar`可能是其安装程序或源码。 10. **progressUpload.rar**...

    安卓图片上传和文件上传带jsp服务端源码

    综上所述,这个资源提供了Android客户端与JSP服务端配合完成图片和文件上传的完整示例,涵盖了从客户端的文件选择、网络请求到服务端的文件处理、安全性保障等多个关键环节。开发者可以通过研究和实践这个源码,提升...

    安卓图片上传和文件上传带jsp服务端源码.zip

    10. **性能优化**:为了提高用户体验,可以采用断点续传、多线程上传、进度显示等技术,同时服务端也要做好负载均衡和并发处理。 这套源码是一个学习和实践Android与JSP交互、文件上传技术的宝贵资源,对于开发者来...

    参数,图片上传android客户端和服务端

    - **断点续传**:对于大文件,可以考虑实现断点续传功能,提高上传的可靠性。 - **分块上传**:对于特别大的图片,可以分割成多个部分并行上传,提升上传速度。 综上所述,图片上传涉及Android客户端的文件选择、...

    android手机客户端上传文件到客户端(web应用)_源代码代码

    - **解析请求**:使用Commons FileUpload库解析请求中的多部分数据,获取上传的文件。 - **存储文件**:将接收到的文件保存到服务器的指定目录,可能需要考虑文件命名冲突和存储空间管理。 - **返回响应**:根据...

    Servlet爬虫下载器.rar

    为提高下载效率,可以采用多线程下载、缓冲区优化、断点续传等技术。例如,使用ExecutorService创建固定大小的线程池,每个线程处理一个下载任务,避免过度消耗服务器资源。 总结,Servlet爬虫下载器是一个结合了...

Global site tag (gtag.js) - Google Analytics