原理
将文件的二进制流切割成指定大小的块儿,对每一块儿加唯一标识,方便文件按顺序合成
步骤
- 读取文件并进行切割
const FILE_PER_PICE_SIZE = 1024*1024*5
export const splitFile = (file) => {
let start = 0
let end
let index = 0
const { size = 0, name = '' } = file || {}
// 最后一片需要至少为FILE_PER_PICE_SIZE大
const totalPieces = Math.floor(size / FILE_PER_PICE_SIZE)
const chucks = []
while (start < size) {
if (index === totalPieces - 1) {
chucks.push({ chuck: file.slice(start), index: index + 1 })
break
}
end = start + FILE_PER_PICE_SIZE
chucks.push({ chuck: file.slice(start, end), index: index + 1 })
start = end
index++
}
return {
total: chucks.length,
chucks,
name,
}
}
- 文件传输前的准备,通过s3.createMultipartUpload得到此次传输的关键信息(UploadId和Key)
/* 取自官方文档 */
var params = {
Bucket: "examplebucket",
Key: "largeobject"
};
s3.createMultipartUpload(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
返回data信息如下
data = {
Bucket: "examplebucket",
Key: "largeobject",
UploadId: "ibZBv_75gd9r8lH_gqXatLdxMVpAlj6ZQjEs.OwyF3953YdwbcQnMA2BLGn8Lx12fQNICtMw5KyteFeHw.Sjng--"
}
*/
});
- 使用s3.uploadPart和上一个接口返回的UploadId和Key逐一传输文件片段
/* 取自官方文档*/
var params = {
Body: <Binary String>, // 文件片段放于该处
Bucket: "examplebucket",
Key: "largeobject",
PartNumber: 1, // 范围为[1, 10000]
UploadId: "xadcOB_7YPBOJuoFiQ9cz4P3Pe6FIZwO4f7wN93uHsNBEw97pl5eNwzExg0LAT2dUN91cOmrEQHDsP3WA60CEg--"
};
s3.uploadPart(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
返回信息如下,同时需要记录该Etag和PartNumber的对应关系
data = {
ETag: "\"d8c2eafd90c266e19ab9dcacc479f8af\""
}
*/
});
- 当所有片段均成功上传后,获取文件在s3上路径
/* 取自官方文档*/
var params = {
Bucket: "examplebucket",
Key: "bigobject",
MultipartUpload: {
Parts: [
{
ETag: "\"d8c2eafd90c266e19ab9dcacc479f8af\"",
PartNumber: 1
},
{
ETag: "\"d8c2eafd90c266e19ab9dcacc479f8af\"",
PartNumber: 2
}
]
},
UploadId: "7YPBOJuoFiQ9cz4P3Pe6FIZwO4f7wN93uHsNBEw97pl5eNwzExg0LAT2dUN91cOmrEQHDsP3WA60CEg--"
};
s3.completeMultipartUpload(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
Bucket: "acexamplebucket",
ETag: "\"4d9031c7644d8081c2829f4ea23c55f7-2\"",
Key: "bigobject",
Location: "https://examplebucket.s3.amazonaws.com/bigobject" // 资源的url(我们需要的部分)
}
*/
});
- 如果上传过程中某一个片段传输有问题,可取消本次上传
/* 取自官方文档*/
var params = {
Bucket: "examplebucket",
Key: "bigobject",
UploadId: "xadcOB_7YPBOJuoFiQ9cz4P3Pe6FIZwO4f7wN93uHsNBEw97pl5eNwzExg0LAT2dUN91cOmrEQHDsP3WA60CEg--"
};
s3.abortMultipartUpload(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});