Ajax+Java实现大文件切割上传

技术体系:html5(formdata) + java + servlet3.0+maven + tomcat7

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>大文件切割上传</title>
 6 <style>
 7     #wrap{width:600px; height:400px; border:1px solid #ccc; margin:10px auto;}
 8     
 9 </style>
10 </head>
11 <body>
12     <p>文件上传:<input type="file" id="file" onchange="uploadFile(this);"></p>
13 </body>
14 </html>
15 <script>
16     function uploadFile(file){
17         var File = file.files[0];
18         var totalSize = File.size; //文件总大小
19         var splitSize = 10 * 1024 * 1024; //10M 切割文件大小
20         var len = Math.ceil(totalSize/splitSize);
21         var fileName = File.name;
22         var xhr = new XMLHttpRequest();
23         var isLast = false;
24         var step = Math.ceil(100/len);
25         for(var i = 0 ; i< len;i++){
26             blob = File.slice(i*splitSize,splitSize*(i+1));
27             isLast = (i == len-1) ? true:false;
28             var result = upload(blob,i);
29             console.log("上传结果:" + result);
30         }
31         
32         function upload(blob,index){
33             var formData = new FormData();
34             formData.append("index",index);
35             formData.append("fileName",fileName);
36             formData.append("isLast",isLast);
37             formData.append("splitSize",splitSize);
38             formData.append("file",blob);
39             xhr.open("POST", "ajax4.do",false);
40             xhr.send(formData);
41             return xhr.responseText;
42         }
43 
44     }
45     
46 </script>

后台代码:

 1 package com.sgepit.ajax;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.annotation.MultipartConfig;
 7 import javax.servlet.annotation.WebServlet;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 import javax.servlet.http.Part;
12 
13 @WebServlet("/ajax4.do")
14 @MultipartConfig
15 public class Ajax4 extends HttpServlet {
16     
17      final String uploadPath = "D:/uploadFile/";
18     
19     @Override
20     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
21         String index = req.getParameter("index");
22         String fileName = req.getParameter("fileName");
23         String isLast = req.getParameter("isLast");
24         String splitSize = req.getParameter("splitSize");
25         splitSize = null == splitSize ? "0" : splitSize;
26         
27         int size = Integer.parseInt(splitSize);
28         
29         Part part = req.getPart("file");
30         try {
31              if(null != part && part.getSize() != 0){
32                  StringBuffer sbRealPath = new StringBuffer();
33                  sbRealPath.append(uploadPath).append(index).append(".").append("part");  
34                   //写入文件  
35                  part.write(sbRealPath.toString());
36                  if("true".equals(isLast)){ //如果是最后一次加载,准备合并文件
37                      FileUtil fileUtil = new FileUtil();
38                      fileUtil.mergePartFiles(uploadPath, ".part", size, uploadPath+fileName);
39                      Thread.sleep(3000); //睡眠3秒以后再删除
40                      fileUtil.deleteSplitFiles(uploadPath,".part");
41                  }
42                  resp.getWriter().write("success");
43              }
44         } catch (Exception e) {
45             e.printStackTrace();
46         }
47         
48     }
49 
50 }

 工具方法:

  1 package com.sgepit.ajax;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FilenameFilter;
  6 import java.io.IOException;
  7 import java.io.RandomAccessFile;
  8 import java.util.ArrayList;
  9 import java.util.Collections;
 10 import java.util.Comparator;
 11 import java.util.concurrent.ArrayBlockingQueue;
 12 import java.util.concurrent.ThreadPoolExecutor;
 13 import java.util.concurrent.TimeUnit;
 14 
 15 /**
 16  * 文件处理辅助类
 17  * 
 18  */
 19 public class FileUtil {
 20 
 21     /**
 22      * 获取指定目录下特定文件后缀名的文件列表(不包括子文件夹)
 23      * @param dirPath  目录路径
 24      * @param suffix   文件后缀
 25      * @return
 26      */
 27     public static ArrayList<File> getDirFiles(String dirPath,final String suffix) {
 28         File path = new File(dirPath);
 29         File[] fileArr = path.listFiles(new FilenameFilter() {
 30             public boolean accept(File dir, String name) {
 31                 String lowerName = name.toLowerCase();
 32                 String lowerSuffix = suffix.toLowerCase();
 33                 if (lowerName.endsWith(lowerSuffix)) {
 34                     return true;
 35                 }
 36                 return false;
 37             }
 38 
 39         });
 40         ArrayList<File> files = new ArrayList<File>();
 41 
 42         for (File f : fileArr) {
 43             if (f.isFile()) {
 44                 files.add(f);
 45             }
 46         }
 47         return files;
 48     }
 49 
 50 
 51     /**
 52      * 合并文件
 53      * 
 54      * @param dirPath 上传文件所在的目录名称
 55      * @param partFileSuffix 拆分文件后缀名
 56      * @param partFileSize拆分文件的字节数大小
 57      * @param mergeFileName 合并后的文件名
 58      * @throws IOException
 59      */
 60     public void mergePartFiles(String dirPath, String partFileSuffix,
 61             int partFileSize, String mergeFileName) throws IOException {
 62         ArrayList<File> partFiles = FileUtil.getDirFiles(dirPath, partFileSuffix);
 63         Collections.sort(partFiles, new FileComparator());
 64 
 65         RandomAccessFile randomAccessFile = new RandomAccessFile(mergeFileName,"rw");
 66         randomAccessFile.setLength(partFileSize * (partFiles.size() - 1)
 67                 + partFiles.get(partFiles.size() - 1).length());
 68         randomAccessFile.close();
 69 
 70         ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
 71                 partFiles.size(), partFiles.size() * 3, 1, TimeUnit.SECONDS,
 72                 new ArrayBlockingQueue<Runnable>(partFiles.size() * 2));
 73 
 74         for (int i = 0; i < partFiles.size(); i++) {
 75             threadPool.execute(new MergeRunnable(i * partFileSize,mergeFileName, partFiles.get(i)));
 76         }
 77     }
 78     
 79     /**删除临时文件
 80      * @param dirPath
 81      * @param partFileSuffix
 82      */
 83     public void deleteSplitFiles(String dirPath,String partFileSuffix){
 84         ArrayList<File> partFiles = FileUtil.getDirFiles(dirPath, partFileSuffix);
 85         for (int i = 0; i < partFiles.size(); i++) {
 86             partFiles.get(i).delete();
 87         }
 88         
 89     }
 90 
 91     /**
 92      * 根据文件名,比较文件 ,根据文件名排序
 93      */
 94     private class FileComparator implements Comparator<File> {
 95         public int compare(File o1, File o2) {
 96             return o1.getName().compareToIgnoreCase(o2.getName());
 97         }
 98     }
 99 
100     /**
101      * 合并处理Runnable
102      * 
103      */
104     private class MergeRunnable implements Runnable {
105         long startPos;
106         String mergeFileName;
107         File partFile;
108 
109         public MergeRunnable(long startPos, String mergeFileName, File partFile) {
110             this.startPos = startPos;
111             this.mergeFileName = mergeFileName;
112             this.partFile = partFile;
113         }
114 
115         public void run() {
116             RandomAccessFile rFile;
117             try {
118                 rFile = new RandomAccessFile(mergeFileName, "rw");
119                 rFile.seek(startPos);
120                 FileInputStream fs = new FileInputStream(partFile);
121                 byte[] b = new byte[fs.available()];
122                 fs.read(b);
123                 fs.close();
124                 rFile.write(b);
125                 rFile.close();
126             } catch (IOException e) {
127                 e.printStackTrace();
128             }
129         }
130     }
131 
132 }

备注:一定要注意,在maven环境下,启动tomcat的时候,一定要用tomcat7:run, 而不是tomcat:run,否则无法正常使用。(踩坑了)

原文地址:https://www.cnblogs.com/tengri/p/5555548.html