我正在寻找一种方法来在浏览器前端拆分任何文本/数据文件,然后再将其作为多个文件上传。我的限制是每次上传 40KB。因此,如果用户上传一个 400KB 的文件,在上传到服务器之前,它会在前端将该文件分割成 10 个单独的块或 10 个单独的文件。
目前,我正在通过将此文件转换为 Base64 格式的字符串,然后将此字符串分割为 40KB,将其分成 10 个单独的块。从那里我上传每个块,文件名为 chunk-1-of-10、chunk-2-of-10...
当拉下这些文件时,我只需将所有这些块连接回去并将其从 Base64 反转换为其文件格式。
有更好的方法吗?是否有一个库可以处理所有这些而不是从头开始编写?我不确定 base64 路线是否是执行此操作的最佳方法。
无需使用FileReader将内容读取到ram中 使用base64只会增加您需要上传的内容的大小,base64占用约33%的大小
使用 Blob.slice 获取块
blob 切片(块)不会增加内存,它只会创建对旧 blob 的新引用,并更改偏移量和新的大小,以从其开始读取的位置。
当
fetch
发送数据时,它将直接从磁盘传输到网络,甚至不接触主线程。
// simulate a file from a input
const file = new File(['a'.repeat(1000000)], 'test.txt')
const chunkSize = 40000
const url = 'https://httpbin.org/post'
for (let start = 0; start < file.size; start += chunkSize) {
const chunk = file.slice(start, start + chunkSize)
const fd = new FormData()
fd.set('data', chunk)
await fetch(url, { method: 'post', body: fd }).then(res => res.text())
}
您可以使用
FileReader
来避免进行 Base64 编码,然后以二进制形式发送:
const url = 'http://www.example.com/upload';
document.getElementById('file-uploader').addEventListener('change', function(e) {
const size = 40000;
var reader = new FileReader();
var buf;
var file = document.getElementById('file-uploader').files[0];
reader.onload = function(e) {
buf = new Uint8Array(e.target.result);
for (var i = 0; i < buf.length; i += size) {
var fd = new FormData();
fd.append('fname', [file.name, i+1, 'of', buf.length].join('-'));
fd.append('data', new Blob([buf.subarray(i, i + size)]));
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
// Uploaded.
};
oReq.send(fd);
}
}
reader.readAsArrayBuffer(file);
});
<input type="file" id="file-uploader"/>