一、使用场景:

1.大文件上传

2.网络环境环境不好,存在需要重传风险的场景

二、名词解释:

切片上传:也叫分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。

断点续传:是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。

三、实现流程步骤:

我们先来个简单的文件上传案例:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>文件上传</title><style>html,body {display: flex;align-items: center;justify-content: center;height: 100%;}</style></head><body><script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.js"></script><input type="file" name="file" id="ipt" /><input type="button" οnclick="getData()" value="get请求数据"/><button οnclick="upload()" type="button"> 上传</button><script>function getData(){axios.get("http://localhost:9528/uname?name=abc").then((res) => {console.log(res.data);});}function upload() {const file = ipt.files[0];const formData = new FormData();formData.append("formData", file, file.name);console.log(formData);axios.post("http://localhost:9528/upload", formData).then((res) => {console.log(formData, res);});}</script></body>
</html>

node服务端

const multiparty = require("multiparty");
const bodyParser = require("body-parser");
const path = require("path");
const express = require("express");
const app = express();
const cors = require('cors')
const fs = require("fs");
function resolvePath(dir) {return path.join(__dirname, dir);
}app.use(cors())
app.use(express.static(resolvePath("/public")));
app.use(bodyParser.json({ limit: "50mb" }));
app.use(bodyParser.urlencoded({ extended: true }));app.post("/upload", function (req, res) {const form = new multiparty.Form({ uploadDir: "public" });form.parse(req);form.on("file", function (name, file) {console.log(name, file);const { path, originalFilename } = file;fs.renameSync(path, `public/${originalFilename}`);res.json({url: `http://localhost:9528/${originalFilename}`,message: "发送成功",});});
});
app.get('/uname',function(req,res){console.log(req.query,req.params);// res.json({a:1,b:2})res.send({ name: "yang", age: 18 });
})app.use(function (err, req, res, next) {console.log('server错误',err);res.send({err:err,message: "server错误"})
})const port = 9528;
app.listen(port, function () {console.log(`listen port ${port}`);
});

测试上传:

可以看到这里已经上传成功,payload是一个二进制文件。服务端指定目录下就多了一个文件

一个简单的文件上传就完成了,现在开始切片上传功能开发,切片上传就是把一个文件切分成很多小文件,本来上传一个大文件,现在改成上传很多小文件

分片上传:

我们知道使用 <input type="file" name="file" /> 元素选择一个文件之后,会得到 File 对象,而 File 对象 又继承 Blob,正好 Blob 对象有个方法叫 slice。这个方法和数组的 slice 方法使用基本相同,它可以获取待上传文件的某一部分,经过 slice 方法处理之后得到的结果也是一个 Blob。

思路:

1、将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;

2、初始化一个分片上传任务,返回本次分片上传唯一标识;

3、按照一定的策略(串行或并行)发送各个分片数据块;

4、发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件。

前端代码:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>分片上传</title><style>html,body {display: flex;align-items: center;justify-content: center;height: 100%;}</style></head><body><script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.js"></script><script src="https://xiaojinhe-cdn.iyoudui.cn/upload/common/2022129/spark-md5.min.js"></script><input type="file" name="file" id="ipt" /><button οnclick="upload(0)">上传</button><script>const chunkSize = 1024 * 1024; // 默认分片大小为1兆。1kb = 1024byte, 1m = 1024 kbfunction upload(index) {const file = ipt.files[0];if (!file) return alert("请您先选择要上传的文件~~");const { name, type, size } = file;// 生成文件hashconst spark = new SparkMD5.ArrayBuffer();spark.append(file);const hexHash = spark.end();// 生成文件后缀const extName = name.substring(name.lastIndexOf("."));const startIndex = chunkSize * index;// 文件上传完,终止递归同时合并文件if (startIndex > size) {axios.post("http://localhost:9528/merge", {fileName: name,hexHash,extName,}).then((res) => {console.log(res);});return;}const endIndex =startIndex + chunkSize > size ? size : startIndex + chunkSize;const blobPart = file.slice(startIndex, endIndex, type);// FormData 直接上传切片后的文件,文件名默认为 blob( filename="blob")// 这里通过 File 给个文件名const blobFile = new File([blobPart], `${hexHash}-${index}${extName}`, {type,});// 创建虚拟表单进行文件上传const vform = new FormData();vform.append("vform", blobFile);axios.post("http://localhost:9528/upload", vform,{onUploadProgress(e) {console.log('进度', e.loaded / e.total);}}).then((res) => {// 分片 => 通过递归实现upload(++index);});}</script></body>
</html>

server新增路由:

app.post("/merge", function (req, res) {const { fileName, hexHash, extName } = req.body;const readDir = fs.readdirSync(resolvePath("./temp"));readDir.sort((a, b) => a - b).map(chunkPath => {fs.appendFileSync(resolvePath(`public/${fileName}`),fs.readFileSync(resolvePath(`temp/${chunkPath}`)));fs.rmSync(resolvePath(`temp/${chunkPath}`));});// fs.rmdirSync(resolvePath("./temp"));res.json({url: `http://localhost:9528/${fileName}`,message: "merge发送成功"});
});

测试切片上传:

分片上传完成,服务端就有了这个上传完成视频。

断点续传:

前面在分片上传的时候,每片chunks都有文件唯一性md5code的文件片段${hexHash}-${index}${extName},如果用户选择了重新上传,后端需要根据此文件的 MD5 检索出来文件已经上传的部分,前端续传。

四、补充:

代码都是简易实现的业务逻辑,真正项目上都不用自己手写,GitHub和各大云都有完善的组件库,功能更完善,逻辑更严谨。附地址:

阿里云:如何在OSS中实现分片上传_对象存储 OSS-阿里云帮助中心

腾讯云:对象存储 上传对象-SDK 文档-文档中心-腾讯云

七牛云:JavaScript SDK历史文档1.x_SDK 下载_对象存储 - 七牛开发者中心

百度上传组件:Web Uploader

前端大文件上传及切片上传-提升上传效率相关推荐

  1. 前端大文件上传和下载(分片上传)

    前端大文件上传和下载(分片上传) 一.问题 日常业务中难免出现前端需要向后端传输大型文件的情况,这时单次的请求不能满足传输大文件的需求,就需要用到分片上传 业务需求为:用户可以上传小于20G的镜像文件 ...

  2. 前端大文件上传解决方案

    本人在2010年时使用swfupload为核心进行文件的批量上传的解决方案.见文章:WEB版一次选择多个文件进行批量上传(swfupload)的解决方案. 本人在2013年时使用plupload为核心 ...

  3. FTP上传大文件时连接重置或者中断,重新连接上传也出现同样情况处理办法

    上传大文件的时候经常连接被重置或者中断,重新连接上传出现同样错误,具体错误如下图所示: 原因:机房防火墙设置了tcp空闲5分钟中断,如果使用被动模式上传较大的文件,上传速度比较慢时容易造成超时,所以连 ...

  4. 前端大文件上传断点续传解决方案

    之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...

  5. 前端必学 - 大文件上传如何实现

    前端必学 - 大文件上传如何实现 写在前面 问题分析 开始操作 一.文件如何切片 二.得到原文件的hash值 三.文件上传 四.文件合并 技术点总结[重要] 一.上传文件? 二.显示进度 三.暂停上传 ...

  6. formdata上传文件_大文件分片断点上传实现思路以及方案

    作者:yeyan1996| 来源:掘金https://juejin.im/post/5dff8a26e51d4558105420ed 前言 我在面试的时候确实被问到了这个问题,而且是一道在线 codi ...

  7. vue 文件及描述信息一起上传_用Vue实现一个大文件上传和断点续传

    前言 这段时间面试官都挺忙的,频频出现在博客文章标题,虽然我不是特别想蹭热度,但是实在想不到好的标题了-.-,蹭蹭就蹭蹭 :) 事实上我在面试的时候确实被问到了这个问题,而且是一道在线 coding ...

  8. antd upload手动上传_SpringBoot 如何上传大文件?

    最近遇见一个需要上传超大大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  9. SpringBoot如何上传大文件

    最近遇见一个需要上传超大大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

最新文章

  1. 安卓9.0官方系统升级包_华为、荣耀公布可升级安卓10.0机型,你的手机在名单之内吗?...
  2. 酷派删除android系统软件,【玩机教程】酷派手机root后不可删除系统自带程序+组件中英对照...
  3. Windows 8.1 应用再出发 - 几种更新的控件
  4. 拓端tecdat|Python多项式Logistic逻辑回归进行多类别分类和交叉验证准确度箱线图可视化
  5. Winlogon、LSASS、Userinit
  6. 模拟题【枚举计数】咒语
  7. 数据结构和算法(Java),上
  8. 不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱
  9. 理科生学酒店管理好一点还是计算机,酒店管理专业是文科还是理科
  10. Raft 共识算法3-日志复制
  11. ElasticSearch(7.2.2)-搜索的简单使⽤
  12. AssertionError: Egg-link *** does not match installed location ***
  13. 2019 湖湘杯 pwn strng2
  14. 第一次数据分析师面试
  15. 隆重推荐几本幼儿教育的书籍
  16. Python英文词频统计(哈姆雷特)程序示例
  17. 华为交换机:三层交换机实现vlan间通信
  18. 最新kali之dbd
  19. unrecognized relocation (0x2a) in section `.text`
  20. android系统广播汇总

热门文章

  1. 海丝一号-中国-2020
  2. 数字IC设计流程(全),芯片设计流程,集成电路设计流程
  3. 机械臂速成小指南(八):运动学建模(标准DH法)
  4. Java学习整理系列之Java枚举类型的原理
  5. 阶段性总结(HTML)
  6. 超方便的验证码套件Captcha Genie,帮你轻松在网页上制作出图片验证码!(下)
  7. 仅记录deepin 安装 2007版本Microsoft Office Word/Powerpoint/Excel/Visio
  8. xss实现获取网站源码
  9. java如何实现e的次方_在java中如何输入e^x(x为变量)还有如何输入e(e为自然对数的底数)?...
  10. OpennVINS运行、评估笔记