切片上传一般用于大型文件上传,切成多个部分分开上传。
整体实现思路:
- 预先设置切片大小。
- 计算总切片次数
- 循环调用上传
import axios from 'axios';
/**
* 请求参数封装为 FormData 对象
* @param params 参数
* @returns {FormData}
*/
const packageFormData = (params) => {
const data = new FormData();
Object.keys(params).forEach(function(key) {
data.append(key, params[key]);
});
return data;
}
/**
* 上传文件
* @param options 配置参数
* @param options.url 上传接口地址
* @param options.params 请求参数
* @param options.file File文件对象
* @param options.onUploadProgress 上传进度事件
* @param options.filename File文件键名,默认 file
* @returns {Promise}
*/
export const uploadFile = (options) => {
const params = options.params || {}; // 没有参数默认为空JSON对象
params[options.filename || 'file'] = options.file; // 没有规定file键名,默认为file
const axiosOptions = {
url: options.url,
method: 'post',
data: packageFormData(params)
};
// 判断是否需要上传进度反馈事件
if (options.onUploadProgress) axiosOptions.onUploadProgress = options.onUploadProgress;
return axios(axiosOptions);
}
/**
* 切片上传
* @param options 配置参数
* @param options.url 上传接口地址
* @param options.params 请求参数
* @param options.file File文件对象
* @param options.onUploadProgress 上传进度事件
* @param options.filename File文件键名,默认 file
* @returns {Promise<[]>}
*/
export async function uploadSection (options) {
const sectionSize = 1 * 1024 * 1024; // 切片大小,超过该值将进行切片上传,字节(b)单位
const sectionTotal = Math.ceil(options.file.size / sectionSize); // 切片次数
const fileSize = options.file.size; // 文件大小
const results = []; // 切片结果返回集
for(let i = 0; i < sectionTotal; i++) {
const startSize = i * sectionSize; // 切片开始位置
// 切片结尾位置,判断如果是最后一次直则是文件大小
const endSize = i === sectionSize - 1 ? fileSize : (i + 1) * sectionSize;
const new_options = {...options}; // 复制原有的 options
new_options.file = options.file.slice(startSize, endSize);
if (options.onUploadProgress) {
new_options.onUploadProgress = (progressEvent) => {
options.onUploadProgress({
loaded: startSize + progressEvent.loaded,
total: fileSize
});
};
}
results.push(await uploadFile(new_options));
}
return results;
}
如果其他问题可添加QQ 2697604576,一起探讨前端。