热门IT资讯网

【原创】webuploader分片上传(前后端分离)

发表于:2024-11-26 作者:热门IT资讯网编辑
编辑最后更新 2024年11月26日,项目地址:https://download.csdn.net/download/zxcnlmx/10389632功能描述1、webuploader是百度研发的上传组件,文档不是特别规整,但是也够用了。

项目地址:

https://download.csdn.net/download/zxcnlmx/10389632

功能描述

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);      }  }  
0