Vue.Js及Java实现文件分片上传代码实例

 更新时间:2020年06月12日 09:23:38   作者:LifeOfCoding  
这篇文章主要介绍了Vue.Js及Java实现文件分片上传代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

说明

代码从项目中剥离修改,未经测试,仅提供思路。

前端

upload(file) {
 //从后台获取已经上传的文件分片数
 getIdx(md5)
  .then(function(res) {
   let retry = 3;
   uploadPart(retry, file, res.data);
  })
  .catch(); 
}

uploadPart(retry, file, idx) {
 //设置分片大小(单位Byte)
 let bufferLength = 1024 * 1024 * 5;
 //计算开始的切割点,idx是上传成功的分片数,未上传过文件则开始点为0
 let start = idx * bufferLength;
 //全部上传完毕或重试次数用完则退出
 if(start>=file.size || retry<=0) return;
 //计算分割的位置
 let end = start + bufferLength;
 //如果分割点超出文件大小,回退分割点
 if (end > file.size) {end = fileSize;}
 //切割文件
 var chunk = file.slice(start, end);
 //创建 formData 对象并添加数据
 let formData = new FormData();
 formData.set("file", chunk);
 //如果是第一次上传,连同文件块数量也上传
 if (start == 0) { 
  //计算文件切片总数,向上取整
  let chunkNum = Math.ceil(file.size / bufferLength);
  formData.set("total", chunkNum);
 }
 //上传文件的api,此处使用axios发送请求
 doUpload(formData)
  //发送成功,则上传下一片,递归调用方法
  .then(function() {
   retry = xx;//刷新重试次数
   uploadPart(retry, file, ++idx);
  })
  //发送失败
  .catch(function() {
   retry--;//重试次数减一
   //重试上传这一片
   uploadPart(retry, file, idx);
  });
},

文件分片上传的前端关键代码只有一句:

//切割文件
var chunk = file.slice(start, end);

通过slice方法来切割文件,然后文件上传的流程视业务和具体技术而定,此处是使用axios发送请求,用递归调用上传文件块。
需要注意的是,Blob.slice(start, end),文件块包含start指向的字节,而不包含end指向的字节,在使用时要注意Blob的边界。

mozilla对slice的说明

后端

/**合并文件的实际操作*/
public static void doMergeFiles(String outFile, String[] files) {
  //设置缓存大小
  int BUFSIZE = 1024 * 1024;
  //排序。文件后缀名是文件的顺序。
  Arrays.sort(files);
  //输出流
  FileChannel outChannel = null;
  //标记最后的一个文件
  String lastFlag = files[files.length-1];
  try {
    outChannel = new FileOutputStream(outFile).getChannel();
    //遍历文件列表
    for(String f : files){
      //最后一块文件用真实大小设置缓存,避免自动填充数据造成的md5不一致
      if(lastFlag.equals(f)){
        File last = new File(f);
        BUFSIZE = (int) last.length();//获取文件的大小并设置成缓存的大小
      }
      FileChannel fc = new FileInputStream(f).getChannel();
      //用ByteBuffer创建缓存
      ByteBuffer bb = ByteBuffer.allocate(BUFSIZE);
      while(fc.read(bb) != -1){//把数据读到缓存
        bb.flip();//重置游标
        outChannel.write(bb);//写入数据
        bb.clear();//清空数据
      }
      fc.close();//关闭流
    }
  } catch (IOException ioe) {
    ioe.printStackTrace();
  } finally {
    try {if (outChannel != null) {outChannel.close();}} catch (IOException ignore) {}
  }
}

  后端的关键是合并文件,当上传完最后一块文件就进行文件的合并。使用ByteBuffer缓存,使用FileChannel进行文件的读写完成合并操作。在保存文件时,文件名取一致,文件的后缀名则取文件块的顺序,比如第一块文件是“xxx.01”,第10块是“xxx.10”,注意,个位数前面要补“0”,这样可以直接用Array.sort()进行排序。

  为提高性能,可以适当设置缓存大小,可以边上传文件边合并,不必等到文件都上传了才合并。

拓展

  此处的文件上传是一次上传一片,上传成功才开始上传下一片。如果前端不是使用javascript,能开启使用多线程的话,可以改成同时上传多片文件提高上传速度。已经上传的文件分片用bitmap存储,上传文件前,从后台获取已上传的文件分片的bitmap数据然后解析,多线程处理未上传的文件分片。

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

相关文章

  • Java并发多线程编程之CountDownLatch的用法

    Java并发多线程编程之CountDownLatch的用法

    这篇文章主要介绍了Java并发多线程编程之CountDownLatch的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 如何计算Java对象占用了多少空间?

    如何计算Java对象占用了多少空间?

    在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小,需要的朋友可以参考下
    2016-01-01
  • Java常量池详解

    Java常量池详解

    下面小编就为大家带来一篇浅谈java常量池。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-09-09
  • logback使用filter过滤日志操作

    logback使用filter过滤日志操作

    这篇文章主要介绍了logback使用filter过滤日志操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Spring6.x对调度和异步执行的注解支持示例详解

    Spring6.x对调度和异步执行的注解支持示例详解

    这篇文章主要为大家介绍了Spring6.x对调度和异步执行的注解支持示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • SpringBoot使用Jsp的示例代码

    SpringBoot使用Jsp的示例代码

    这篇文章主要介绍了SpringBoot使用Jsp的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • SpringMVC拦截器运行原理及配置详解

    SpringMVC拦截器运行原理及配置详解

    这篇文章主要介绍了SpringMVC拦截器运行原理及配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringBoot新手入门的快速教程

    SpringBoot新手入门的快速教程

    这篇文章主要给大家介绍了关于SpringBoot新手入门的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用SpringBoot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • Java数组操作经典例题大总结

    Java数组操作经典例题大总结

    数组是在内存中存储相同数据类型的连续的空间,声明一个数组就是在内存空间中划出一串连续的空间,下面这篇文章主要给大家介绍了关于Java数组操作经典例题的相关资料,需要的朋友可以参考下
    2022-03-03
  • IntelliJ IDEA编译项目报错

    IntelliJ IDEA编译项目报错 "xxx包不存在" 或 "找不到符号"

    这篇文章主要介绍了IntelliJ IDEA编译项目报错 "xxx包不存在" 或 "找不到符号" ,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08

最新评论