JavaScript

超轻量级php框架startmvc

webuploader分片上传的实现代码(前后端分离)

更新时间:2020-07-26 02:00:01 作者:startmvc
本文介绍了webuploader分片上传的实现代码(前后端分离),分享给大家,具体如下:WebUploade

本文介绍了webuploader分片上传的实现代码(前后端分离),分享给大家,具体如下:

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。采用大文件分片并发上传,极大的提高了文件上传效率。(这个是从官网上直接copy的解释)

功能描述

1、webuploader是百度研发的上传组件,文档不是特别规整,但是也够用了。

2、前端使用官网的上传图片demo,在此基础上代码略微调整做分片。既可以上传图片也可以上传文件。文件超过分片大小才启用分片。

3、分片上传已做md5校验,达到秒传的效果。分片以后需要合并,可以先分片后合并,也可以边分片边合并,本示例采用的是边分片边合并的方案。

4、后端用springboot做框架搭建。springMVC做rest服务,开启跨域访问。

5、容器用springboot内置的tomcat插件,运行Application的main方法即可启动服务;

显示效果

关键代码前端


WebUploader.Uploader.register({ 
 'name': 'webUploaderHookCommand', 
 'before-send-file': 'beforeSendFile', 
 "before-send": "beforeSend" 
 }, { 
 beforeSendFile: function(file) { 
 var task = new WebUploader.Deferred(); 
 fileName = file.name; 
 fileSize = file.size; 
 (new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024).progress(function(percentage) {}).then(function(val) { 
 fileMd5 = val; 
 var url = checkUrl; 
 var data = { 
 type: 0, 
 fileName: fileName, 
 fileMd5: fileMd5, 
 fileSize: fileSize 
 }; 
 $.ajax({ 
 type: "POST", 
 url: url, 
 data: data, 
 cache: false, 
 async: false, // 同步 
 timeout: 1000, // todo 超时的话,只能认为该分片未上传过 
 dataType: "json", 
 error: function(XMLHttpRequest, textStatus, errorThrown) { 
 file.statusText = 'server_error'; 
 task.reject(); 
 } 
 }).then(function(data, textStatus, jqXHR) { 
 if(data.rtn == 0) { 
 if(data.obj == 1) { 
 file.statusText = 'file_existed'; 
 task.reject(); 
 } else { 
 task.resolve(); 
 } 
 } else { 
 task.reject(); 
 } 
 }); 
 }); 
 return task.promise(); 
 }, 
 beforeSend: function(block) { 
 var task = new WebUploader.Deferred(); 
 var url = checkUrl; 
 var data = { 
 type: 1, 
 fileName: fileName, 
 fileMd5: fileMd5, 
 chunk: block.chunk, 
 fileSize: block.end - block.start 
 }; 
 $.ajax({ 
 type: "POST", 
 url: url, 
 data: data, 
 cache: false, 
 async: false, // 同步 
 timeout: 1000, // todo 超时的话,只能认为该分片未上传过 
 dataType: "json" 
 }).then(function(data, textStatus, jqXHR) { 
 if(data.rtn == 0 && data.obj == 1) { 
 task.reject(); // 分片存在,则跳过上传 
 } else { 
 task.resolve(); 
 } 
 }); 
 this.owner.options.formData.fileMd5 = fileMd5; 
 this.owner.options.formData.chunkSize = chunkSize; 
 return task.promise(); 
 } 
 }); 
 
 // 实例化 
 uploader = WebUploader.create({ 
 pick: { 
 id: '#filePicker', 
 label: '点击选择文件' 
 }, 
 formData: { 
 uid: 123 
 }, 
 dnd: '#dndArea', //指定文件拖拽的区域 
 paste: '#uploader', //指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为document.body. 
 swf: '../plugins/webuploader/Uploader.swf', 
 chunked: true, 
 chunkSize: chunkSize, 
 chunkRetry: false, 
 threads: 1, 
 server: uploadUrl, 
 // runtimeOrder: 'flash', 
 
 // accept: { 
 // title: 'Images', 
 // extensions: 'gif,jpg,jpeg,bmp,png', 
 // mimeTypes: 'image/*' 
 // }, 
 // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。 
 disableGlobalDnd: true, 
 fileNumLimit: 300 //限制多文件上传的个数 
 //fileSizeLimit: 200 * 1024 * 1024, // 限制所有文件的大小 200 M 
 //fileSingleSizeLimit: 50 * 1024 * 1024 // 限制单个文件的大小 50 M 
 }); 

后端


import java.io.File; 
import java.io.IOException; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.stereotype.Service; 
import org.springframework.web.multipart.MultipartFile; 
 
import com.bear.upload.util.FileUtil; 
import com.bear.upload.util.RETURN; 
import com.bear.upload.vo.CheckMd5FileVO; 
import com.bear.upload.vo.UploadVO; 
 
@Service 
public class ChunkUploadService { 
 
 private static Logger LOG = LoggerFactory.getLogger(ChunkUploadService.class); 
 
 @Value("${file.upload.path}") 
 private String UPLOAD_PATH; 
 
 private static final String Delimiter = "-"; 
 
 /** 
 * 上传之前校验(整个文件、分片) 
 * 
 * @param md5FileVO 
 * @return 
 */ 
 public Object check(CheckMd5FileVO md5FileVO) { 
 Integer type = md5FileVO.getType(); 
 Long chunk = md5FileVO.getChunk(); 
 String fileName = md5FileVO.getFileName(); 
 Long fileSize = md5FileVO.getFileSize(); 
 if (type == 0) {// 未分片校验 
 String destfilePath = UPLOAD_PATH + File.separator + fileName; 
 File destFile = new File(destfilePath); 
 if (destFile.exists() && destFile.length() == fileSize) { 
 return RETURN.success("文件已存在,跳过", 1); 
 } else { 
 return RETURN.success("文件不存在", 0); 
 } 
 } else {// 分片校验 
 String fileMd5 = md5FileVO.getFileMd5(); 
 String destFileDir = UPLOAD_PATH + File.separator + fileMd5; 
 String destFileName = chunk + Delimiter + fileName; 
 String destFilePath = destFileDir + File.separator + destFileName; 
 File destFile = new File(destFilePath); 
 if (destFile.exists() && destFile.length() == fileSize) { 
 return RETURN.success("分片已存在,跳过", 1); 
 } else { 
 return RETURN.success("分片不存在", 0); 
 } 
 } 
 } 
 
 /** 
 * 文件上传 
 * 
 * @param file 
 * @param uploadVO 
 * @param appVersion 
 * @return 
 */ 
 public Object upload(MultipartFile file, UploadVO uploadVO) { 
 Long chunk = uploadVO.getChunk(); 
 if (chunk == null) {// 没有分片 
 return UnChunkUpload(file, uploadVO); 
 } else {// 分片 
 return ChunkUpload(file, uploadVO); 
 } 
 } 
 
 /** 
 * 分片上传 
 * 
 * @param file 
 * @param uploadVO 
 * @param appVersion 
 * @return 
 */ 
 public Object ChunkUpload(MultipartFile file, UploadVO uploadVO) { 
 String fileName = uploadVO.getName(); 
 String fileMd5 = uploadVO.getFileMd5(); 
 Long chunk = uploadVO.getChunk();// 当前片 
 Long chunks = uploadVO.getChunks();// 总共多少片 
 
 // 分片目录创建 
 String chunkDirPath = UPLOAD_PATH + File.separator + fileMd5; 
 File chunkDir = new File(chunkDirPath); 
 if (!chunkDir.exists()) { 
 chunkDir.mkdirs(); 
 } 
 // 分片文件上传 
 String chunkFileName = chunk + Delimiter + fileName; 
 String chunkFilePath = chunkDir + File.separator + chunkFileName; 
 File chunkFile = new File(chunkFilePath); 
 try { 
 file.transferTo(chunkFile); 
 } catch (Exception e) { 
 LOG.error("分片上传出错", e); 
 return RETURN.fail("分片上传出错", 1); 
 } 
 // 合并分片 
 Long chunkSize = uploadVO.getChunkSize(); 
 long seek = chunkSize * chunk; 
 String destFilePath = UPLOAD_PATH + File.separator + fileName; 
 File destFile = new File(destFilePath); 
 if (chunkFile.length() > 0) { 
 try { 
 FileUtil.randomAccessFile(chunkFile, destFile, seek); 
 } catch (IOException e) { 
 LOG.error("分片{}合并失败:{}", chunkFile.getName(), e.getMessage()); 
 return RETURN.fail("分片合并失败", 1); 
 } 
 } 
 if (chunk == chunks - 1) { 
 // 删除分片文件夹 
 FileUtil.deleteDirectory(chunkDirPath); 
 
 return RETURN.success("上传成功", 1); 
 } else { 
 return RETURN.fail("上传中...", 1); 
 } 
 } 
 
 /** 
 * 未分片上传 
 * 
 * @param file 
 * @param uploadVO 
 * @param appVersion 
 * @return 
 */ 
 public Object UnChunkUpload(MultipartFile file, UploadVO uploadVO) { 
 String fileName = uploadVO.getName(); 
 // String fileMd5 = uploadVO.getFileMd5(); 
 // 文件上传 
 File destFile = new File(UPLOAD_PATH + File.separator + fileName); 
 if (file != null && !file.isEmpty()) { 
 // 上传目录 
 File fileDir = new File(UPLOAD_PATH); 
 if (!fileDir.exists()) { 
 fileDir.mkdirs(); 
 } 
 if (destFile.exists()) { 
 destFile.delete(); 
 } 
 try { 
 file.transferTo(destFile); 
 return RETURN.success("上传成功", 0); 
 } catch (Exception e) { 
 LOG.error("文件上传出错", e); 
 return RETURN.fail("文件上传出错", 0); 
 } 
 } 
 return RETURN.fail("上传失败", 0); 
 } 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

webuploader分片上传 webuploader分片