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

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

js/jQuery 2024-12-31 10:29:01 5个月前

本文介绍了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);
  }
} 

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

文章版权声明:除非注明,否则均为网络转载文章,转载或复制请以超链接形式并注明出处。

最新资讯

热门资讯