一、背景介绍
现在大文件上传或下载时,大概率要使用分片上传或下载,来达到断点续传的效果。不然一旦网络中断,之前已经上传或下载的一部分就丢失了,需要全部重新上传或下载。
二、分片
分片的操作js已经提供了一个现成的API
Blob.slice
:用于创建一个包含源 Blob的指定字节范围内的数据的新 Blob 对象。
语法:
const blob = instanceOfBlob.slice(start , end , contentType)
start
:可选
这个参数代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。如果你传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说,-10 将会是 Blob 的倒数第十个字节。它的默认值是 0,如果你传入的 start 的长度大于源 Blob 的长度,那么返回的将会是一个长度为 0 并且不包含任何数据的一个 Blob 对象。
end
:可选
这个参数代表的是 Blob 的一个下标,这个下标 -1 的对应的字节将会是被拷贝进新的Blob 的最后一个字节。如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说, -10 将会是 Blob 的倒数第十个字节。它的默认值就是它的原始长度 (size).
contentType
:可选
给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。
三、组合
组合直接使用Blob()
构造函数初始化即可
语法:
const aBlob = new Blob( array, options );
array
:是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings 会被编码为 UTF-8。
options
:是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
type
:默认值为 “”,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。endings
:默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。它是以下两个值中的一个:“native”,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 “transparent”,代表会保持 blob 中保存的结束符不变非标准
四、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<label>
<input id="input" type="file" onchange="fileChange(event)"/>
</label>
<script>
// 文件大于20MB时,设置每个分片大小为20MB
const chunkSize = 20 * 1024 * 1024;
function fileChange(e) {
// 定义一个数组存放所有的分片
const chunks = [];
// 获取文件
const file = e.target.files[0]
const name = file.name
const type = file.type
// 计算总共有多少个分片
const totalChunks = Math.ceil(file.size / chunkSize);
// 进行分片
for (let i = 0; i < totalChunks; i++) {
// 利用slice方法获取每个分片
const start = i * chunkSize;
// 使用Math.min避免超出文件大小
const end = Math.min(file.size, start + chunkSize);
const blob = file.slice(start, end, type);
// 将每个分片添加到数组中
chunks.push(blob);
}
// 在此可以分片提交文件给后端了,具体实现接口请自己解决
console.log(chunks)
// 合并时chunks应该从接口获取,这里默认你已经获取完文件数据并放入chunks中(不要忘记在请求时设置responseType为blob)
// 组合
const newBlob = new Blob(chunks, {
type
});
newBlob.name = name
console.log(newBlob)
// 组合下载测试
const aTag = document.createElement('a')
aTag.download = name
aTag.href = URL.createObjectURL(newBlob)
// 自动点击创建的标签
aTag.click()
}
</script>
</body>
</html>