「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
背景
假如我们现在有一个很大的图片(>20M)要上传到服务器,怎么办?通过FormData,单线上传?
这样上传简单的文件没有问题!但是图片大了,网络满了怎么了办?
答案:文件切片上传,断点上传。
技术
github: github.com/satazor/js-…
npmjs : www.npmjs.com/package/spa…
实现
安装
npm install --save spark-md5
安装好后你的package.json文件中就会多出"spark-md5": "^3.0.0",
计算文件MD5
为什么要计算MD5?
答:因为对于一个文件他的MD5是固定的,如果你不改变文件的内容,MD5是不会变的,这样就可以传值给后端比较文件的准确性和完整性、一致性、不重复。
通过MD5我们可以实现文件的去重
- 一般文件(小于2M)
一种是用SparkMD5.hashBinary() 直接将整个文件的二进制码传入,直接返回文件的md5。
- 体积较大的文件 一般我们做上传的时候推荐使用分片的方式,因为文件的体积不确定,这种方式对于大体积的文件计算更加稳定,还可以获得计算进度的信息。
计算代码如下:
import SparkMD5 from 'spark-md5'
let getMD5 = function (request, callback) {
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
let chunkSize = 2097152 // 每次读取2MB
let file = request.file
let chunks = Math.ceil(file.size / chunkSize)
let currentChunk = 0
let spark = new SparkMD5.ArrayBuffer()
let fileReader = new FileReader()
fileReader.onload = function (e) {
console.info('array buffer', e) // Compute hash
spark.append(e.target.result) // Append array buffer
currentChunk++
if (currentChunk < chunks) {
loadNext()
} else {
console.log('finished loading')
console.info('computed hash', spark.end()) // Compute hash
callback(request, spark.end())
}
}
fileReader.onerror = function () {
console.warn('oops, something went wrong.')
}
function loadNext () {
let start = currentChunk * chunkSize
let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
}
loadNext()
}
export default {getMD5}
生成切片
//把文件切片,生成文件块
createFileChunks(file) {
const chunkSize = 2 * 1024 * 1024;// 把文件分块指定成2M大小
const chunks = [];
let curSize = 0;
while(cur < file.size) {
chunks.push({
index: chunks.length, file: file.slice(curSize, curSize + chunkSize)
});
curSize += size;
}
return chunks;
}
SparkMD5方法
append(str)
添加一个字符串。
appendBinary(str)
添加一个二进制字符串。
end()
完成 md5 的计算,返回 hex 结果。如果raw为真,则将返回二进制字符串的结果。
reset()
重置计算的内部状态。
getState()
返回一个表示内部计算状态的对象。您可以将此状态传递给 setState()。此功能对于恢复增量 md5 很有用。
setState(state)
设置内部计算状态。
destroy()
释放增量缓冲区和其他附加资源使用的内存。
hash(str, raw)
直接散列一个字符串,返回十六进制结果。如果raw为true,则将返回二进制字符串的结果。注意这个函数是static。
hashBinary(str, raw)
直接散列二进制字符串,返回十六进制结果。如果raw为true,则将返回二进制字符串的结果。注意这个函数是static。
SparkMD5.ArrayBuffer方法
append(arr)
添加一个数组缓冲区。
end(raw)
完成 md5 的计算,返回 hex 结果。如果raw为true,则将返回二进制字符串的结果。
reset()
重置计算的内部状态。
destroy()
释放增量缓冲区和其他附加资源使用的内存。
getState()
返回一个表示内部计算状态的对象。您可以将此状态传递给 setState()。此功能对于恢复增量 md5 很有用。
setState(state)
设置内部计算状态。
hash(arr, raw)
直接散列数组缓冲区,返回十六进制结果。如果raw为true,则将返回二进制字符串的结果。注意这个函数是static.