大文件分块上传第二弹(秒传、断点续传)

xiaoxiao2021-02-28  58

关键部分

前端用file.slice()分块前端用FileReader获取每一分块的md5值后端用MultipartFile接受分块文件后端用FileOutputStream拼装分块文件

话不多说,直接上代码,我想这是你们最喜欢的

html

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>HTML5大文件分片上传示例</title> <script src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script src="md5.js"></script> <script> var i = -1; var succeed = 0; var databgein; //开始时间 var dataend; //结束时间 var action=false; //false检验分片是否上传过(默认); true上传文件 var page = { init: function(){ $("#upload").click(function(){ databgein=new Date(); var file = $("#file")[0].files[0]; //文件对象 isUpload(file); }); } }; $(function(){ page.init(); }); function isUpload (file) { //构造一个表单,FormData是HTML5新增的 var form = new FormData();    var r = new FileReader();   r.readAsBinaryString(file); $(r).load(function(e){   var bolb = e.target.result;   var md5 = hex_md5(bolb); form.append("md5", md5); //Ajax提交 $.ajax({ url: "http://localhost:8080//bookQr/test/isUpload", type: "POST", data: form, async: true, //异步 processData: false, //很重要,告诉jquery不要对form进行处理 contentType: false, //很重要,指定为false才能形成正确的Content-Type success: function(data){ var dataObj = eval("("+data+")"); var uuid = dataObj.fileId; var date = dataObj.date; if (dataObj.flag == "1") { //没有上传过文件 upload(file,uuid,md5,date); } else if(dataObj.flag == "2") { //已经上传部分 upload(file,uuid,md5,date);       } else if(dataObj.flag == "3") { //文件已经上传过 alert("文件已经上传过,秒传了!!"); $("#uuid").append(uuid);         } },error: function(XMLHttpRequest, textStatus, errorThrown) { alert("服务器出错!"); } });    }) } /* * file 文件对象 * uuid 后端生成的uuid * filemd5 整个文件的md5 * date 文件第一个分片上传的日期(如:20170122) */ function upload (file,uuid,filemd5,date) { name = file.name; //文件名 size = file.size; //总大小 var shardSize = 5 * 1024 * 1024, //以5MB为一个分片 shardCount = Math.ceil(size / shardSize); //总片数 if (i > shardCount) { i = -1; i = shardCount; } else { if(!action){ i += 1; //只有在检测分片时,i才去加1; 上传文件时无需加1 } } //计算每一片的起始与结束位置 var start = i * shardSize, end = Math.min(size, start + shardSize); //构造一个表单,FormData是HTML5新增的 var form = new FormData(); if(!action){ form.append("action", "check"); //检测分片是否上传 $("#param").append("action==check "); }else{ form.append("action", "upload"); //直接上传分片 form.append("data", file.slice(start,end)); //slice方法用于切出文件的一部分 $("#param").append("action==upload "); } form.append("uuid", uuid); form.append("filemd5", filemd5); form.append("date", date); form.append("name", name); form.append("size", size); form.append("total", shardCount); //总片数 form.append("index", i+1); //当前是第几片 var ssindex = i+1; $("#param").append("index=="+ssindex+"<br/>"); //按大小切割文件段   var data = file.slice(start, end);    var r = new FileReader();   r.readAsBinaryString(data); $(r).load(function(e){   var bolb = e.target.result;   var md5 = hex_md5(bolb); form.append("md5", md5); //Ajax提交 $.ajax({ url: "http://localhost:8080//bookQr/test/upload", type: "POST", data: form, async: true, //异步 processData: false, //很重要,告诉jquery不要对form进行处理 contentType: false, //很重要,指定为false才能形成正确的Content-Type success: function(data){ var dataObj = eval("("+data+")"); var fileuuid = dataObj.fileId; var flag = dataObj.flag; //服务器返回该分片是否上传过 if(!action){ if (flag == "1") { //未上传 action = true; } else if(dataObj.flag == "2") { //已上传   action = false; ++succeed;     } //递归调用     upload(file,uuid,filemd5,date); }else{ //服务器返回分片是否上传成功 //改变界面 ++succeed; $("#output").text(succeed + " / " + shardCount); if (i+1 == shardCount) { dataend=new Date(); $("#uuid").append(fileuuid); $("#usetime").append(dataend.getTime()-databgein.getTime()); } else { //已上传成功,然后检测下一个分片   action = false; //递归调用     upload(file,uuid,filemd5,date);     } } },error: function(XMLHttpRequest, textStatus, errorThrown) { alert("服务器出错!"); } });    }) } </script> </head> <body> <input type="file" id="file" /> <button id="upload">上传</button> <span id="output" style="font-size:12px">等待</span> <span id="usetime" style="font-size:12px;margin-left:20px;">用时</span> <span id="uuid" style="font-size:12px;margin-left:20px;">uuid==</span> <br/> <br/> <br/> <br/> <span id="param" style="font-size:12px;margin-left:20px;">param==</span> </body> </html> 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315

controller

package com.yxtech.sys.controller; import com.yxtech.common.Constant; import com.yxtech.sys.domain.FileRes; import com.yxtech.sys.service.FileResService; import com.yxtech.sys.service.ResService; import com.yxtech.utils.file.FileMd5Util; import com.yxtech.utils.file.NameUtil; import com.yxtech.utils.file.PathUtil; import jodd.datetime.JDateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import tk.mybatis.mapper.entity.Example; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; /** * Created by Administrator on 2015/10/9. */ @RestController @Scope("prototype") @RequestMapping(value = "/test") public class testController { @Autowired private FileResService fileResService; @Autowired private ResService resService; /** * 上传文件 * * @param request * @return * @throws IllegalStateException * @throws IOException */ @RequestMapping(value = "/upload") public Map<String, Object> upload( HttpServletRequest request, @RequestParam(value = "data",required = false) MultipartFile multipartFile) throws IllegalStateException, IOException, Exception { String action = request.getParameter("action"); String uuid = request.getParameter("uuid"); String fileName = request.getParameter("name"); String size = request.getParameter("size");//总大小 int total = Integer.valueOf(request.getParameter("total"));//总片数 int index = Integer.valueOf(request.getParameter("index"));//当前是第几片 String fileMd5 = request.getParameter("filemd5"); //整个文件的md5 String date = request.getParameter("date"); //文件第一个分片上传的日期(如:20170122) String md5 = request.getParameter("md5"); //分片的md5 //生成上传文件的路径信息,按天生成 String savePath = Constant.FILE_PATH + File.separator + date; String saveDirectory = PathUtil.getAppRootPath(request) + savePath + File.separator + uuid; //验证路径是否存在,不存在则创建目录 File path = new File(saveDirectory); if (!path.exists()) { path.mkdirs(); } //文件分片位置 File file = new File(saveDirectory, uuid + "_" + index); //根据action不同执行不同操作. check:校验分片是否上传过; upload:直接上传分片 Map<String, Object> map = null; if("check".equals(action)){ String md5Str = FileMd5Util.getFileMD5(file); if (md5Str != null && md5Str.length() == 31) { System.out.println("check length =" + md5.length() + " md5Str length" + md5Str.length() + " " + md5 + " " + md5Str); md5Str = "0" + md5Str; } if (md5Str != null && md5Str.equals(md5)) { //分片已上传过 map = new HashMap<>(); map.put("flag", "2"); map.put("fileId", uuid); map.put("status", true); return map; } else { //分片未上传 map = new HashMap<>(); map.put("flag", "1"); map.put("fileId", uuid); map.put("status", true); return map; } }else if("upload".equals(action)){ //分片上传过程中出错,有残余时需删除分块后,重新上传 if (file.exists()) { file.delete(); } multipartFile.transferTo(new File(saveDirectory, uuid + "_" + index)); } if (path.isDirectory()) { File[] fileArray = path.listFiles(); if (fileArray != null) { if (fileArray.length == total) { //分块全部上传完毕,合并 String suffix = NameUtil.getExtensionName(fileName); File newFile = new File(PathUtil.getAppRootPath(request) + savePath, uuid + "." + suffix); FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加写入 byte[] byt = new byte[10 * 1024 * 1024]; int len; FileInputStream temp = null;//分片文件 for (int i = 0; i < total; i++) { int j = i + 1; temp = new FileInputStream(new File(saveDirectory, uuid + "_" + j)); while ((len = temp.read(byt)) != -1) { System.out.println("-----" + len); outputStream.write(byt, 0, len); } } //关闭流 temp.close(); outputStream.close(); //修改FileRes记录为上传成功 Example example = new Example(FileRes.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("md5",fileMd5); FileRes fileRes = new FileRes(); fileRes.setStatus(Constant.ONE); fileResService.updateByExampleSelective(fileRes,example); }else if(index == 1){ //文件第一个分片上传时记录到数据库 FileRes fileRes = new FileRes(); String name = NameUtil.getFileNameNoEx(fileName); if (name.length() > 50) { name = name.substring(0, 50); } fileRes.setName(name); fileRes.setSuffix(NameUtil.getExtensionName(fileName)); fileRes.setUuid(uuid); fileRes.setPath(savePath + File.separator + uuid + "." + fileRes.getSuffix()); fileRes.setSize(Integer.parseInt(size)); fileRes.setMd5(fileMd5); fileRes.setStatus(Constant.ZERO); fileRes.setCreateTime(new Date()); this.fileResService.insert(fileRes); } } } map = new HashMap<>(); map.put("flag", "3"); map.put("fileId", uuid); map.put("status", true); return map; } /** * 上传文件前校验 * * @param request * @return * @throws IOException */ @RequestMapping(value = "/isUpload") public Map<String, Object> isUpload(HttpServletRequest request) throws Exception { String md5 = request.getParameter("md5"); Example example = new Example(FileRes.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("md5", md5); List<FileRes> list = fileResService.selectByExample(example); Map<String, Object> map = null; if (list == null || list.size() == 0) { //没有上传过文件 String uuid = UUID.randomUUID().toString(); map = new HashMap<>(); map.put("flag", "1"); map.put("fileId", uuid); map.put("date", new JDateTime().toString("YYYYMMDD")); map.put("status", true); } else { FileRes fileRes = list.get(0); //求文件上传日期 SimpleDateFormat sdf=new SimpleDateFormat("YYYYMMDD"); Date date=new Date(); String strDate=sdf.format(date); if(fileRes.getStatus()==0){ //文件上传部分 map = new HashMap<>(); map.put("flag", "2"); map.put("fileId", fileRes.getUuid()); map.put("date",strDate); map.put("status", true); }else if(fileRes.getStatus()==1){ //文件上传成功 map = new HashMap<>(); map.put("flag", "3"); map.put("fileId", fileRes.getUuid()); map.put("date",strDate); map.put("status", true); } } return map; } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217

FileMd5Util

package com.yxtech.utils.file; import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; import java.security.MessageDigest; /** * @author cuihao * @create 2017-01-20-15:13 */ public class FileMd5Util { public static final String KEY_MD5 = "MD5"; public static final String CHARSET_ISO88591 = "ISO-8859-1"; /** * Get MD5 of one file:hex string,test OK! * * @param file * @return */ public static String getFileMD5(File file) { if (!file.exists() || !file.isFile()) { return null; } MessageDigest digest = null; FileInputStream in = null; byte buffer[] = new byte[1024]; int len; try { digest = MessageDigest.getInstance("MD5"); in = new FileInputStream(file); while ((len = in.read(buffer, 0, 1024)) != -1) { digest.update(buffer, 0, len); } in.close(); } catch (Exception e) { e.printStackTrace(); return null; } BigInteger bigInt = new BigInteger(1, digest.digest()); return bigInt.toString(16); } /*** * Get MD5 of one file!test ok! * * @param filepath * @return */ public static String getFileMD5(String filepath) { File file = new File(filepath); return getFileMD5(file); } /** * MD5 encrypt,test ok * * @param data * @return byte[] * @throws Exception */ public static byte[] encryptMD5(byte[] data) throws Exception { MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); md5.update(data); return md5.digest(); } public static byte[] encryptMD5(String data) throws Exception { return encryptMD5(data.getBytes(CHARSET_ISO88591)); } /*** * compare two file by Md5 * * @param file1 * @param file2 * @return */ public static boolean isSameMd5(File file1,File file2){ String md5_1= FileMd5Util.getFileMD5(file1); String md5_2= FileMd5Util.getFileMD5(file2); return md5_1.equals(md5_2); } /*** * compare two file by Md5 * * @param filepath1 * @param filepath2 * @return */ public static boolean isSameMd5(String filepath1,String filepath2){ File file1=new File(filepath1); File file2=new File(filepath2); return isSameMd5(file1, file2); } public static void main(String[] args) { // for(int i=1;i<79;i++){ // File file = new File("F:\\bookQr_SYS\\target\\bookQr\\files\\20170122\\2124b3f9-a4c8-4297-a182-6249010dcd72\\2124b3f9-a4c8-4297-a182-6249010dcd72_"+i); File file = new File("F:\\bookQr_SYS\\target\\bookQr\\files\\20170122\\2124b3f9-a4c8-4297-a182-6249010dcd72.mp4"); String md5Str = getFileMD5(file); System.out.println(""+md5Str.length()+" "+md5Str); // } } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108

NameUtil

/** * Created by Administrator on 2015/10/12. */ public class NameUtil { /** * Java文件操作 获取文件扩展名 */ public static String getExtensionName(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length() - 1))) { return filename.substring(dot + 1); } } return filename.toLowerCase(); } /** * Java文件操作 获取不带扩展名的文件名 */ public static String getFileNameNoEx(String filename) { if ((filename != null) && (filename.length() > 0)) { int dot = filename.lastIndexOf('.'); if ((dot > -1) && (dot < (filename.length()))) { return filename.substring(0, dot); } } return filename.toLowerCase(); } public static void main(String[] args) { String str = "AAAbb.jpg"; System.out.println(getExtensionName(str).toLowerCase()); System.out.println(getFileNameNoEx(str).toUpperCase()); } } 1234567891011121314151617181920212223242526272829303132333435363738 1234567891011121314151617181920212223242526272829303132333435363738

PathUtil

import com.yxtech.sys.controller.MailController; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * Created by Administrator on 2015/10/12. */ public class PathUtil { /** * * @param request * @return 返回结果类似于 “F:\workSpace\bookQr\src\main\webapp\” */ public static String getAppRootPath(HttpServletRequest request){ //ServletActionContext.getServletContext().getRealPath("/")+"upload"; return request.getSession().getServletContext().getRealPath("/"); } /** *自定义文件保存路径 * @param request */ public static String getCustomRootPath(HttpServletRequest request){ String path = ""; Properties prop = new Properties(); InputStream in = MailController.class.getResourceAsStream("/config/jdbc.properties"); try { prop.load(in); path = prop.getProperty("FILE_PATH").trim(); } catch (IOException e) { e.printStackTrace(); } return path; } /** * * @param request * @return http://www.qh.com:8080/projectName */ public static String getHttpURL(HttpServletRequest request) { StringBuffer buff = new StringBuffer(); buff.append("http://"); buff.append(request.getServerName()); buff.append(":"); buff.append(request.getServerPort()); buff.append(request.getContextPath()); return buff.toString(); } }
转载请注明原文地址: https://www.6miu.com/read-53167.html

最新回复(0)