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


Posted in Javascript onSeptember 10, 2018

本文介绍了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分片上传的实现代码(前后端分离)

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

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

关键代码前端

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

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

Javascript 相关文章推荐
javascript字典探测用户名工具
Oct 05 Javascript
jquery ajax请求实例深入解析
Nov 26 Javascript
javascript放大镜效果的简单实现
Dec 09 Javascript
纯javascript判断查询日期是否为有效日期
Aug 24 Javascript
jQuery实现带分组数据的Table表头排序实例分析
Nov 24 Javascript
jQuery动态改变多行文本框高度的方法
Sep 07 Javascript
微信小程序 解析网页内容详解及实例
Feb 22 Javascript
JavaScript实现短暂提示框功能
Apr 04 Javascript
利用React Router4实现的服务端直出渲染(SSR)
Jan 07 Javascript
使用imba.io框架得到比 vue 快50倍的性能基准
Jun 17 Javascript
小程序双头slider选择器的实现示例
Mar 31 Javascript
jQuery实现二级导航菜单的示例
Sep 30 jQuery
在Vue 中使用Typescript的示例代码
Sep 10 #Javascript
ES6使用export和import实现模块化的方法
Sep 10 #Javascript
Vuejs 实现简易 todoList 功能 与 组件实例代码
Sep 10 #Javascript
浅谈微信小程序flex布局基础
Sep 10 #Javascript
微信小程序文章详情页面实现代码
Sep 10 #Javascript
Bootbox将后台JSON数据填充Form表单的实例代码
Sep 10 #Javascript
JavaScript读写二进制数据的方法详解
Sep 09 #Javascript
You might like
社区(php&&mysql)四
2006/10/09 PHP
PHP个人网站架设连环讲(二)
2006/10/09 PHP
PHP 5.0对象模型深度探索之对象复制
2008/03/27 PHP
PHP版网站缓存加快打开速度的方法分享
2012/06/03 PHP
php全局变量和类配合使用深刻理解
2013/06/05 PHP
PHP6连接SQLServer2005的三部曲
2016/04/15 PHP
PHP实现对xml进行简单的增删改查(CRUD)操作示例
2017/05/19 PHP
PHP7 windows支持
2021/03/09 PHP
IE6背景图片不缓存问题解决方案及图片使用策略多个方法小结
2012/05/14 Javascript
javascript实现动态侧边栏代码
2014/02/19 Javascript
jquery搜索框效果实现方法
2015/01/16 Javascript
JQuery实现鼠标移动图片显示描述层的方法
2015/06/25 Javascript
javascript插件开发的一些感想和心得
2016/02/28 Javascript
jQuery改变form表单的action,并进行提交的实现代码
2016/05/25 Javascript
jQuery实现产品对比功能附源码下载
2016/08/09 Javascript
js定时器实例分享
2016/12/20 Javascript
Ionic2开发环境搭建教程
2020/08/20 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
webpack 从指定入口文件中提取公共文件的方法
2018/11/13 Javascript
JSON字符串操作移除空串更改key/value的介绍
2019/01/05 Javascript
详解从react转职到vue开发的项目准备
2019/01/14 Javascript
vue 组件中使用 transition 和 transition-group实现过渡动画
2019/07/09 Javascript
Python深入学习之内存管理
2014/08/31 Python
python中利用队列asyncio.Queue进行通讯详解
2017/09/10 Python
Django 实现前端图片压缩功能的方法
2019/08/07 Python
详解Css3新特性应用之过渡与动画
2017/01/10 HTML / CSS
意大利辅助药品、药物和补品在线销售:FarmaEurope
2020/04/29 全球购物
工作表现自我评价
2014/02/08 职场文书
高一新生军训感言
2014/03/02 职场文书
国家税务局干部作风整顿整改措施
2014/09/18 职场文书
学校师德师风自我剖析材料
2014/09/29 职场文书
承诺函范文
2015/01/21 职场文书
mysq启动失败问题及场景分析
2021/07/15 MySQL
九大龙王魂骨,山龙王留下躯干骨,榜首死的最憋屈(被捏碎)
2022/03/18 国漫
联想win10摄像头打不开怎么办?win10笔记本摄像头打不开解决办法
2022/04/08 数码科技
前端框架ECharts dataset对数据可视化的高级管理
2022/12/24 Javascript