93 lines
3.2 KiB
JavaScript
93 lines
3.2 KiB
JavaScript
import assert from "assert";
|
||
import { OakUploadException } from '../../types/Exception';
|
||
// 辅助方法:将文件切片
|
||
export async function sliceFile(file, chunkSize, partCount) {
|
||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||
// 微信小程序环境下,file 可能是临时文件路径字符串
|
||
if (typeof file === 'string') {
|
||
return sliceFileForMp(file, chunkSize, partCount);
|
||
}
|
||
else {
|
||
assert(false, '小程序环境下得到不为string的文件');
|
||
}
|
||
}
|
||
assert(file instanceof File, '分片上传仅支持 File 类型的文件');
|
||
const chunks = [];
|
||
for (let i = 0; i < partCount; i++) {
|
||
const start = i * chunkSize;
|
||
const end = Math.min(start + chunkSize, file.size);
|
||
chunks.push(file.slice(start, end));
|
||
}
|
||
return chunks;
|
||
}
|
||
// 小程序环境下的文件分片
|
||
export async function sliceFileForMp(filePath, chunkSize, partCount) {
|
||
const fs = wx.getFileSystemManager();
|
||
const tempDir = `${wx.env.USER_DATA_PATH}/oak_upload_temp`;
|
||
assert(chunkSize <= 10 * 1024 * 1024, '小程序下,单个分片大小不能超过 10MB'); // 微信小程序限制单个文件不能超过10MB
|
||
// 确保临时目录存在
|
||
try {
|
||
fs.accessSync(tempDir);
|
||
}
|
||
catch (e) {
|
||
fs.mkdirSync(tempDir, false);
|
||
}
|
||
const chunks = [];
|
||
// 读取文件信息
|
||
const fileStat = fs.statSync(filePath);
|
||
assert(!Array.isArray(fileStat), '无法获取文件信息');
|
||
const fileSize = fileStat.size;
|
||
// 读取每个分片并写入临时文件
|
||
for (let i = 0; i < partCount; i++) {
|
||
const start = i * chunkSize;
|
||
const length = Math.min(chunkSize, fileSize - start);
|
||
try {
|
||
// 读取分片数据
|
||
const data = await new Promise((resolve, reject) => {
|
||
fs.readFile({
|
||
filePath: filePath,
|
||
encoding: 'binary',
|
||
position: start,
|
||
length: length,
|
||
success: (res) => resolve(res.data),
|
||
fail: reject
|
||
});
|
||
});
|
||
// 写入临时文件
|
||
const tempFilePath = `${tempDir}/chunk_${Date.now()}_${i}.temp`;
|
||
await new Promise((resolve, reject) => {
|
||
fs.writeFile({
|
||
filePath: tempFilePath,
|
||
encoding: 'binary',
|
||
data: data,
|
||
success: () => resolve(),
|
||
fail: reject
|
||
});
|
||
});
|
||
chunks.push(tempFilePath);
|
||
}
|
||
catch (err) {
|
||
console.error('分片读取失败:', err);
|
||
// 清理已创建的临时文件
|
||
await cleanTempFiles(chunks);
|
||
throw new OakUploadException(`分片 ${i + 1} 读取失败: ${err}`);
|
||
}
|
||
}
|
||
return chunks;
|
||
}
|
||
// 清理临时文件
|
||
export async function cleanTempFiles(tempFiles) {
|
||
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
||
return;
|
||
}
|
||
const fs = wx.getFileSystemManager();
|
||
for (const filePath of tempFiles) {
|
||
try {
|
||
fs.unlinkSync(filePath);
|
||
}
|
||
catch (err) {
|
||
console.warn(`清理临时文件失败: ${filePath}`, err);
|
||
}
|
||
}
|
||
}
|