思路:前台上传文件分片到后台存储,并保存路径为数组,上传完毕后合并,使用ajax同步上传,后期再优化 后台代码: package com.savethink.web.opera.controller.video; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import com.savethink.web.opera.common.ControllerResult; import com.savethink.web.opera.common.StringUtil; /** * 视频上传 * * @author SaveThink * */ @Controller @RequestMapping(value = "/videoUploadController") public class VideoUploadController { @Value("${upload.file.root}") private String uploadRoot; @Value("${upload.file.video}") private String uploadVideo; @Value("${upload.file.video.type}") private String uploadVideoType; // 分片上传 @RequestMapping(value = "/upload", method = RequestMethod.POST) @ResponseBody public ControllerResult upload(HttpServletRequest request) { ControllerResult result = new ControllerResult(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; // 获得文件: MultipartFile file = multipartRequest.getFile("file"); int index = Integer.parseInt(multipartRequest.getParameter("index")); File uploadFile = new File(getUploadVideoPath() + File.separator + "temp", index+".tmp"); if (!uploadFile.getParentFile().exists()) { // 判断文件父目录是否存在 uploadFile.getParentFile().mkdirs(); } createFile(file, uploadFile); File originalFilePath = new File(uploadFile.getParentFile().getPath().toString() + File.separator + file.getOriginalFilename()); result.msg = uploadFile.toPath().toString(); result.message = originalFilePath.toPath().toString(); return result; } // 合并所有文件 @RequestMapping(value = "/merge", method = RequestMethod.POST) @ResponseBody public ControllerResult merge(@RequestParam(value = "tempsFile[]") String[] tempsFile, HttpServletRequest request) { ControllerResult result = new ControllerResult(); String originalFilePath = request.getParameter("originalFilePath"); boolean flag = mergeFiles(tempsFile, originalFilePath); return result; } // 获取视频上传的路径 private String getUploadVideoPath() { StringBuffer sb = new StringBuffer(uploadRoot); sb.append(File.separator); sb.append(uploadVideo); return sb.toString(); } // 转储文件 public static boolean createFile(MultipartFile file,File uploadFile) { boolean flag = false; try { file.transferTo(uploadFile); flag = true; } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return flag; } public static List<File> handleTempsPath(String filePath) { File file = new File(filePath); File[] fs = file.listFiles(); List<File> files = new ArrayList<>(); for(int i = 0; i < fs.length; i++) { if(fs[i].isFile()) { files.add(fs[i]); System.out.println(fs[i].getName()); } } return files; } // 利用nio FileChannel合并多个文件 @SuppressWarnings("resource") public static boolean mergeFiles(String[] fpaths, String resultPath) { if (fpaths == null || fpaths.length < 1 || StringUtil.isEmpty(resultPath)) { return false; } if (fpaths.length == 1) { return new File(fpaths[0]).renameTo(new File(resultPath)); } File[] files = new File[fpaths.length]; for (int i = 0; i < fpaths.length; i ++) { files[i] = new File(fpaths[i]); if (StringUtil.isEmpty(fpaths[i]) || !files[i].exists() || !files[i].isFile()) { return false; } } File resultFile = new File(resultPath); try { FileChannel resultFileChannel = new FileOutputStream(resultFile, true).getChannel(); for (int i = 0; i < fpaths.length; i ++) { FileChannel blk = new FileInputStream(files[i]).getChannel(); resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size()); blk.close(); } resultFileChannel.close(); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } for (int i = 0; i < fpaths.length; i ++) { files[i].delete(); } return true; } }
前台html代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>文件上传</title> <style> #test { width: 200px; height: 100px; border: 1px solid green; display: none; } #img { width: 50px; height: 50px; display: none; } #upimg { text-align: center; font: 8px/10px '微软雅黑', '黑体', sans-serif; width: 300px; height: 10px; border: 1px solid green; } #load { width: 0%; height: 100%; background: green; text-align: center; } </style> </head> <body> <form enctype="multipart/form-data"> <div id="upimg"> <div id="load"></div> </div> <input type="file" name="file" id="videoFile" /> <input type="button" value="上传" onclick="upload();" /> <input type="submit" value="submit" /> </form> <div id="test">测试是否DIV消失</div> <script type="text/javascript" src="lib/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript"> var token = parent.window.document.getElementById("token").value; // 发送请求 function upload(){ // 进度条 var progressBar=document.getElementById('load'); var num=document.getElementById('upimg'); var tempsFile=new Array(); var blob = document.getElementById("videoFile").files[0]; // 每片文件5M var perPiece = 1024 * 1024 * 50; var originalFilePath; var start = 0, end = 0, index = 0, totalPieces, filesize = blob.size, filename = blob.name; // 计算文件切片总数 // totalPieces = Math.ceil(filesize / perPiece); totalPieces = filesize%perPiece==0?filesize/perPiece:filesize/perPiece+1; console.log("==================="); console.log("切片总数:"+totalPieces); console.log("索引:"+index); // 如果文件为空,则退出 if(!blob){ alert('请选择文件'); return; } // 上传文件 while(start < filesize) { // 切片上传 end = start + perPiece; if(end > filesize) { // 一次性上传 end = filesize; } // 分割文件核心部分slice var chunk = blob.slice(start, end); var sliceIndex = blob.name + index; console.log("=========sliceIndex==========:"+sliceIndex); var formData = new FormData(); formData.append('token',token); formData.append("file", chunk, filename); formData.append("totalPieces", totalPieces); formData.append("index", index); $.ajax({ url: "videoUploadController/upload", type: "POST", async:false, cache: false, data: formData, processData: false, contentType: false, }).done(function(res) { tempsFile.push(res.msg); originalFilePath = res.message; // 进度条 pecent=100*(end)/filesize; if(pecent>100){ pecent=100; } progressBar.style.width=pecent+'%'; progressBar.innerHTML = parseInt(pecent)+'%'; }).fail(function(res) { alert('文件发送失败,请重新发送'); progressBar.style.width='0%'; }); start = end; index ++; } merge(tempsFile, originalFilePath); console.log("上传成功"); } function merge(tempsFile, originalFilePath) { $.ajax({ url:"videoUploadController/merge", dataType:"json", async:false, data:{"token":token, "originalFilePath":originalFilePath, "tempsFile": tempsFile}, type:"POST", beforeSend:function(){ //请求前的处理 }, success:function(req){ }, complete:function(){ //请求完成的处理 }, error:function(){ //请求出错处理 } }); } </script> </body> </html>