返回
大文件上传优雅解决传输失败问题,保证用户传输体验
前端
2023-11-24 09:21:23
前言
在大文件传输过程中,如果因刷新页面或临时失败导致传输中断,用户需要从头重新传输,非常影响用户体验。因此,需要一种方法来记录传输进度,以便下次直接从失败处继续传输。
解决方法
使用localStorage来记录传输进度。localStorage是浏览器提供的存储API,可以存储字符串键值对。具体步骤如下:
- 计算文件MD5、哈希值或其他唯一标识。
- 将计算出的唯一标识存储在localStorage中,键为文件的唯一标识,值为文件的传输进度。
- 当文件传输失败时,从localStorage中读取文件的唯一标识,并从上次传输进度处继续传输。
代码示例
// React组件
import React, { useState } from 'react';
const FileUpload = () => {
const [file, setFile] = useState(null);
const [progress, setProgress] = useState(0);
const handleChange = (e) => {
setFile(e.target.files[0]);
};
const handleSubmit = (e) => {
e.preventDefault();
// 计算文件MD5
const md5 = calculateMD5(file);
// 将MD5和传输进度存储在localStorage中
localStorage.setItem(md5, progress);
// 开始上传文件
uploadFile(file, md5, progress);
};
const uploadFile = (file, md5, progress) => {
// 创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 设置上传事件监听器
xhr.upload.addEventListener('progress', (e) => {
// 计算传输进度
const newProgress = Math.round((e.loaded / e.total) * 100);
// 更新localStorage中的传输进度
localStorage.setItem(md5, newProgress);
// 更新组件状态
setProgress(newProgress);
});
// 设置请求头
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
// 打开请求
xhr.open('POST', 'http://example.com/upload');
// 发送请求
xhr.send(file);
};
return (
<form onSubmit={handleSubmit}>
<input type="file" onChange={handleChange} />
<button type="submit">上传</button>
<progress value={progress} max="100" />
</form>
);
};
export default FileUpload;
// Koa路由
const router = require('koa-router')();
router.post('/upload', async (ctx) => {
// 获取文件
const file = ctx.request.files.file;
// 计算文件MD5
const md5 = calculateMD5(file);
// 从localStorage中读取传输进度
const progress = localStorage.getItem(md5);
// 如果传输进度不为0,则从上次传输进度处继续传输
if (progress) {
ctx.request.req.headers['Content-Range'] = `bytes ${progress}-`;
}
// 将文件保存到服务器
const filePath = `./uploads/${file.name}`;
const fileStream = fs.createWriteStream(filePath);
fileStream.write(file.data);
fileStream.end();
// 返回成功信息
ctx.body = {
success: true,
message: '文件上传成功',
};
});
总结
通过使用localStorage记录传输进度,可以优雅地解决大文件上传传输失败问题,保证用户传输体验的顺畅性。