断点上传 水平较菜 ,多包涵
完善之后的代码:(不再通过发起多次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包,可能有多余的:
相关推荐
本文将详细介绍如何在Java中实现文件的上传与下载,并重点讨论断点续传和断点上传的技术实现。 首先,让我们从基础开始。在Web端进行文件上传通常涉及到HTML表单、Servlet或Spring MVC等技术。在HTML中,可以使用`...
总结,实现Android应用中的图片上传和断点续传下载涉及多个技术点,包括Android权限管理、Intent交互、网络请求、文件操作、服务器端Servlet配置以及异常处理等。熟练掌握这些技术,能够让你构建出更完善的Android...
- 大多数服务器要求文件上传使用`multipart/form-data`格式,因为它可以携带多个部分,包括文件和额外的参数。 - 在Android客户端,可以使用`HttpURLConnection`的`setFixedLengthStreamingMode()`或`...
这个项目为你提供了一个基础的Android文件下载系统的实例,你可以根据实际需求对其进行修改和扩展,例如添加断点续传、多线程下载等高级功能。通过理解并实践这些知识点,你将能够更好地理解和构建Android与服务器...
在Web应用程序中,通常使用Servlet API来处理服务器端的文件上传。`HttpServletRequest`对象提供了`getParts()`方法,可以用来获取上传的文件部分。你需要在Servlet中解析这些部分并保存到服务器的文件系统、数据库...
同时,对于大文件,可能需要采用断点续传,确保在网络不稳定时能够恢复上传。 总之,文件上传是一个涉及客户端与服务器交互的复杂过程,需要理解HTTP协议、文件I/O、网络编程以及可能的云存储服务的API。...
1. **分块上传**:由于Java标准库的`Servlet`或`HttpURLConnection`不支持大文件流式上传,因此通常采用分块上传的方式。将大文件分割成小块,逐个上传,这样可以避免一次性加载整个文件到内存中,减少内存压力。 2...
3. **性能优化**:对于大文件上传,考虑分块上传和断点续传,以减少内存占用和提高稳定性。 4. **并发处理**:服务器端需要考虑并发处理多个上传请求的能力。 5. **日志记录**:记录上传日志,便于问题排查和监控...
2. **Servlet**:在传统的 Java Web 应用中,我们通常会使用 Servlet 来处理文件上传和下载。`javax.servlet.http.HttpServletRequest` 可以用来获取上传文件的信息,如文件名、大小等。`javax.servlet....
9. **UUploader**:UUploader是一个流行的JavaScript文件上传控件,支持多文件选择、断点续传等功能,如`UUploaderBeta60028.EXE`和`UUploaderBeta60028.rar`可能是其安装程序或源码。 10. **progressUpload.rar**...
综上所述,这个资源提供了Android客户端与JSP服务端配合完成图片和文件上传的完整示例,涵盖了从客户端的文件选择、网络请求到服务端的文件处理、安全性保障等多个关键环节。开发者可以通过研究和实践这个源码,提升...
10. **性能优化**:为了提高用户体验,可以采用断点续传、多线程上传、进度显示等技术,同时服务端也要做好负载均衡和并发处理。 这套源码是一个学习和实践Android与JSP交互、文件上传技术的宝贵资源,对于开发者来...
- **断点续传**:对于大文件,可以考虑实现断点续传功能,提高上传的可靠性。 - **分块上传**:对于特别大的图片,可以分割成多个部分并行上传,提升上传速度。 综上所述,图片上传涉及Android客户端的文件选择、...
- **解析请求**:使用Commons FileUpload库解析请求中的多部分数据,获取上传的文件。 - **存储文件**:将接收到的文件保存到服务器的指定目录,可能需要考虑文件命名冲突和存储空间管理。 - **返回响应**:根据...
为提高下载效率,可以采用多线程下载、缓冲区优化、断点续传等技术。例如,使用ExecutorService创建固定大小的线程池,每个线程处理一个下载任务,避免过度消耗服务器资源。 总结,Servlet爬虫下载器是一个结合了...