日常开发中使用 javascript 实现文件上传非常简单,但是在上传大文件时,由于连接不稳定,上传可能会中途失败,导致整个过程需要重新开始,从而造成时间和带宽的浪费,导致用户流失。
解决这个问题的实用方法是实施文件切片/分块,即将大文件分成较小的部分,然后一次上传一个,全部上传完成后,在服务端合并文件即可。这样遇到错误时,只是当前切片/分块上传失败,重新尝试上传该切片/分块即可,而不需要全部重新开始。本文就分享一下在客户端用 JavaScript 实现大文件切片/分块上传的方法。
JavaScript 实现文件切片/分块
在 JavaScript 中,Blob
对象的slice
方法允许我们实现文件切片/分块。slice
方法可用于创建一个新Blob(片)
,其中包含指定起点和终点的原始Blob
中的数据。
假设我们要上传一个视频文件。基本过程如下:
- 通过 HTML input 元素选择文件。
- 使用 JavaScript 将文件分割成块。
- 逐块发送到服务器。
示例代码:
// HTML input 输入框
<input type="file" id="file-upload">
// JavaScript 文件处理
const fileInput = document.getElementById('file-upload');
fileInput.addEventListener('change', handleFileUpload);
function handleFileUpload(event) {
const file = event.target.files[0];
const chunkSize = 1024 * 1024; // 每块大小 (1MB)
let start = 0;
while (start < file.size) {
uploadChunk(file.slice(start, start + chunkSize));
start += chunkSize;
}
}
function uploadChunk(chunk) {
const formData = new FormData();
formData.append('file', chunk);
// Make a request to the server
fetch('/upload-endpoint', {
method: 'POST',
body: formData,
});
}
在上面的示例中,我们首先使用 HTML input 元素选择文件。然后,我们为输入元素添加一个事件监听器,每当有文件被选中,该监听器就会触发handleFileUpload
函数。该函数会将所选文件切成若干块,并调用uploadChunk
函数将每一块上传到服务器。
错误处理和重试机制
在网络连接不稳定的情况下,即便分块很小,但上传请求仍然有可能会失败。因此,我们需要一种机制来处理这些失败。我们可以完善一下uploadChunk
函数,在请求最终失败前重试一定次数:
async function uploadChunk(chunk, retries = 3) {
const formData = new FormData();
formData.append('file', chunk);
try {
await fetch('/upload-endpoint', {
method: 'POST',
body: formData,
});
} catch (error) {
if (retries > 0) {
await uploadChunk(chunk, retries - 1);
} else {
console.error('零五网[www.02405.com]提示:分块上传失败: ', error);
}
}
}
完善后的uploadChunk
函数使用 try-catch 块来封装获取请求。如果请求失败,我们会捕获错误并重试请求。我们会跟踪重试次数,只有在指定的重试次数用完后才会失败。
到此,一个简单的 javascript 文件切片/分块上传功能就实现完成了,接下来在服务端接收请求、合并保存文件即可。也可参考本站的 PHP 实现文件分块上传教程一文。