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

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

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

(0)

相关推荐

  • jQuery webuploader分片上传大文件

    一般在做文件上传的时候,都是通过客户端把要上传的文件上传到服务器,此时上传的文件都在服务器内存,如果上传的是视频等大文件,那么服务器内存就很紧张,而且一般我们都是用flash或者html5做异步上传,如果文件比较大的话,即便是客户端显示文件已经上传了100%,还是会有一个比较长时间的等待,而且当前页面对服务器的请求也会被阻塞. 正常情况下,一般都是在长传完成后,在服务器直接保存. public void ProcessRequest(HttpContext context) { context.

  • webuploader在springMVC+jquery+Java开发环境下的大文件分片上传的实例代码

    注意: 1,webuploader上传组件会和jQuery自带的上传组件冲突,所以不要使用<form>标签中添加上传文件的属性; enctype="multipart/form-data" 2.并且屏蔽ApplicationContext-mvc.xml里面的拦截配置! <!-- 上传拦截,如最大上传值及最小上传值 --> <!--新增加的webuploader上传组件,必须要屏蔽这里的拦截机制 <bean id="multipartRes

  • 使用WebUploader实现分片断点上传文件功能(二)

    写在前面: 这几天,有去研究一下WebUploader上传文件,前面的博客有记录下使用WebUploader简单上传文件的例子,今天就把分片断点上传的例子也记录下吧,在博客园中,也查看了一些资料,基本上后台处理数据都是用的Servlet,或者是SpringMVC,由于最近的项目一直都是Struts2,所以这里就用Struts2中的action来对数据进行处理,达到分片上传文件的效果. 1.什么是分片上传? 顾名思义,就是把文件分成一片片,即让一个文件,分割成好几个小文件,然后再上传.这样做的好处

  • Vue2.0结合webuploader实现文件分片上传功能

    Vue项目中遇到了大文件分片上传的问题,之前用过webuploader,索性就把Vue2.0与webuploader结合起来使用,封装了一个vue的上传组件,使用起来也比较舒爽. 上传就上传吧,为什么搞得那么麻烦,用分片上传? 分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度. 当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件.另外分片传输能够更加实时的跟踪上传进度. 实现后的界面: 主要是两个文件,封装的上传组件和具体的ui页面,上传组件代码下面有列出来

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

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

  • SpringBoot文件分片上传的示例代码

    目录 背景 文件MD5计算 文件分片切割 文件分片接收 检查分片 保存分片 合并分片 云文件分片上传 阿里云OSS 华为云OBS Minio 背景 最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,如图纸,视频等,并且需要在上传大文件过程中进行优化实时展现进度条,进行技术评估后针对框架文件上传进行扩展升级,扩展接口支持大文件分片上传处理,减少服务器瞬时的内存压力,同一个文件上传失败后可以从成功上传分片位置进行断点续传,文件上传成功后再次上

  • PHP实现文件分片上传的实例代码

    PHP用超级全局变量数组$_FILES来记录文件上传相关信息的. 1.file_uploads=on/off 是否允许通过http方式上传文件 2.max_execution_time=30 允许脚本最大执行时间,超过这个时间就会报错 3.memory_limit=50M 设置脚本可以分配的最大内存量,防止失控脚本占用过多内存,此指令只有在编译时设置了. --enable-memory-limit标志的情况下才生效 4.upload_max_filesize=20M 允许上传文件的最大大小,此指

  • 快速掌握jQuery插件WebUploader文件上传

    文件上传是网站和 Web 应用程序的常用功能,一直没有一款完美的文件上传组件,因此让很多开发人员碰到头疼的浏览器兼容问题. WebUploader 是由 Baidu FEX 团队开发的一款以 HTML5 为主,FLASH 为辅的现代文件上传组件.在现代的浏览器里面能充分发挥 HTML5 的优势,同时又不摒弃主流IE浏览器,沿用原来的 FLASH 运行时,兼容 IE6+,iOS 6+, android 4+.采用大文件分片并发上传,极大的提高了文件上传效率. 参考百度官网进行学习借鉴,整理,具体内

  • 使用WebUploader实现上传文件功能(一)

    写在前面: 文件上传方式很多的,对于大文件的上传,在本次项目中也有涉及,主要是用了分片断点上传大文件.所以就去了解了一下WebUploader,先从简单的上传文件开始吧. 在代码中写注释,这样看的比较好点,那就直接上代码来看了解实现的过程吧. 前台jsp页面: <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% String scheme = request.ge

  • 利用Vue3+Element-plus实现大文件分片上传组件

    目录 一.背景 二.技术栈 三.核心代码实现 四.总结 一.背景 实际项目中遇到需要上传几十个G的3d模型文件,传统上传就不适用了. 结合element提供的上传组件自己封装了文件分片上传的组件. 思路: 把文件拆分成若干分片 依次上传分片(每次上传前可校验该分片是否已经上传) 发起合并分片的请求 二.技术栈 Vue3+Ts+Element-Plus 其他库:spark-md5 后端接口: 上传分片接口 校验分片是否已上传接口 合并分片接口 三.核心代码实现 Element组件基础配置 <el-

  • Java axios与spring前后端分离传参规范总结

    目录 前言 一.@RequestParam注解对应的axios传参方法 1.1.params传参(推荐) 1.2.FormData传参 1.3.qs.stringfy传参 二.@RequestBody的axios传参方法 前言 前后端分离开发的场景下,开发人员的工作内容更加专注与专业,但是也产生了一些额外的沟通成本.比如:本文中为大家说明的前后端参数传递与接受方法.本文主要是面对前端使用axios,后端使用Spring进行参数接受的情况进行说明.在使用spring的时候,与前端配合开发,容易出现

  • 基于NodeJS的前后端分离的思考与实践(一)全栈式开发

    前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了"前后端"的定义,引入前端同学都熟悉的NodeJS,试图探索一条全新的前后端分离模式. 随着不同终端(Pad/Mobile/PC)的兴起,对开发人员的要求越来越高,纯浏览器端的响应式已经不能满足用户体验的高要求,我们往往需要针对不同的终端开发定制的版本.为了提升开发效率,前后端分离的需求越来越被重视,后端负责业务/数据接口,前端负责展现/交互逻

随机推荐