uin-app 大文件上传 切片
async uploadFileByChunks(filePath, fileName, extra {}) { // 1. 获取文件大小 const fileInfo await new Promise((resolve, reject) { uni.getFileInfo({ filePath, success: resolve, fail: reject }); }); const totalSize fileInfo.size; const chunkSize UPLOAD_CONFIG.CHUNK_SIZE; const totalChunks Math.ceil(totalSize / chunkSize); // 2. 初始化分片上传获取 uploadId 和服务端文件标识 serverFilePath uni.showLoading({ title: 准备上传..., mask: true }); const initResult await apiInitMultipartUpload({ fileName, fileSize: totalSize, chunkCount: totalChunks, extra }); const uploadId initResult.uploadId; const serverFilePath initResult.filePath; // 后端返回的服务端文件路径 // 3. 循环上传分片 const fs uni.getFileSystemManager(); for (let i 0; i totalChunks; i) { const start i * chunkSize; const end Math.min(start chunkSize, totalSize); // 读取当前分片的二进制数据 const chunkData await new Promise((resolve, reject) { fs.readFile({ filePath, position: start, length: end - start, success: (res) resolve(res.data), fail: reject }); }); // 将分片数据写入临时文件因为 uni.uploadFile 需要文件路径 const tmpChunkPath ${wx.env.USER_DATA_PATH}/chunk_${uploadId}_${i}; await new Promise((resolve, reject) { fs.writeFile({ filePath: tmpChunkPath, data: chunkData, success: resolve, fail: reject }); }); // 上传当前分片chunkIndex 从 1 开始 uni.showLoading({ title: 上传中 ${i 1}/${totalChunks} }); await apiUploadChunk({ uploadId, chunkIndex: i 1, totalChunks, chunkFilePath: tmpChunkPath, // 本地分片文件路径 serverFilePath: serverFilePath, // 后端返回的文件标识 fileName }); // 清理临时分片释放空间 try { fs.unlinkSync(tmpChunkPath); } catch (e) { // 忽略清理错误 } } // 4. 合并分片 uni.showLoading({ title: 正在合并文件... }); const result await apiCompleteMultipartUpload({ uploadId, filePath: serverFilePath, // 使用后端返回的文件标识而不是本地临时路径 fileName, fileSize: totalSize, extra }); return result; // 包含 fileUrl、coverUrl 等字段 },