class FileUploader { constructor({ url, chunkSize = 1024 * 1024, fileName, retryLimit = 3 }) { this.url = url; // 文件路径 this.chunkSize = chunkSize; // 每片大小,默认为 1MB this.fileName = fileName; // 文件名 this.fileSystemManager = my.getFileSystemManager(); // 获取文件系统管理器 this.totalChunks = 0; // 总分片数 } // 开始上传 async startUpload(callback) { try { console.log(this.url) const arrayBuffer = await this.urlToArrayBuffer(this.url); console.log(arrayBuffer) // const fileData = await this.readFileAsArrayBuffer(this.filePath); const fileType = await this.detectFileType(this.filePath); this.fileType = fileType.type; this.fileName = this.fileName + fileType.extension; console.log('detectFileType: success', fileType,arrayBuffer); this.totalChunks = Math.ceil(arrayBuffer.byteLength / this.chunkSize); // 逐片上传 for (let chunkIndex = 0; chunkIndex < this.totalChunks; chunkIndex++) { const chunk = this.getChunk(arrayBuffer, chunkIndex); const base64Chunk = my.arrayBufferToBase64(chunk); // 上传分片,带重试机制 let resObj = await this.uploadChunk(base64Chunk, chunkIndex, this.totalChunks); console.log(`分片 ${chunkIndex + 1}/${this.totalChunks} 上传成功`); callback('success', resObj) } console.log("文件上传成功!"); } catch (error) { callback('error', `${JSON.stringify(error)}`) console.error("文件上传失败:", JSON.stringify(error)); } } async urlToArrayBuffer(url) { return new Promise((resolve, reject) => { // 使用 my.downloadFile 下载文件 my.downloadFile({ url: url, success: async (downloadRes) => { console.log(downloadRes) // const downPath = downloadRes.tempFilePath; // 下载后的路径,后缀名可能被篡改 // this.filePath = downPath // // 使用文件系统读取文件内容 // this.fileSystemManager.readFile({ // filePath: downPath, // success: (res) => { // resolve(res.data); // res.data 是 ArrayBuffer // }, // fail: (err) => { // reject(`读取文件失败: ${err}`); // } // }); if (downloadRes.statusCode === 200) { const downPath = downloadRes.tempFilePath; // 下载后的路径,后缀名可能被篡改 this.filePath = downPath // 使用文件系统读取文件内容 this.fileSystemManager.readFile({ filePath: downPath, success: (res) => { resolve(res.data); // res.data 是 ArrayBuffer }, fail: (err) => { reject(`读取文件失败: ${JSON.stringify(err)}`); } }); } else { reject(`下载失败,状态码: ${downloadRes.statusCode}`); } }, fail: (err) => { reject(`下载失败: ${JSON.stringify(err)}`); } }); }); } // 读取文件为 ArrayBuffer readFileAsArrayBuffer(filePath) { return new Promise((resolve, reject) => { this.fileSystemManager.readFile({ filePath: filePath, success: (res) => resolve(res.data), fail: (err) => reject(err), }); }); } // 检测文件类型 detectFileType(filePath) { console.log(filePath) return new Promise((resolve, reject) => { my.detectFileType({ filePath: filePath, success: (res) => resolve(res), fail: (err) => reject(err), }); }); } // 获取文件的指定分片 getChunk(fileData, chunkIndex) { const start = chunkIndex * this.chunkSize; const end = Math.min(fileData.byteLength, start + this.chunkSize); return fileData.slice(start, end); } // 带重试的分片上传 async uploadChunkWithRetry(base64Chunk, chunkIndex) { let attempt = 0; while (attempt < this.retryLimit) { try { let resObj = await this.uploadChunk(base64Chunk, chunkIndex, this.totalChunks); console.log(`分片 ${chunkIndex + 1}/${this.totalChunks} 上传成功`); return resObj; // 上传成功,退出重试循环 } catch (error) { attempt++; console.warn(`分片 ${chunkIndex + 1} 上传失败,重试次数:${attempt}/${this.retryLimit}`); if (attempt >= this.retryLimit) { throw new Error(`分片 ${chunkIndex + 1} 上传失败,已达最大重试次数`); } } } } // 上传单个分片 uploadChunk(base64Chunk, chunkIndex, totalChunks) { return new Promise((resolve, reject) => { try { let params = { "action": "setStorage", "event": "", "taskId": "117", "params": { content: base64Chunk, // 当前分片的 Base64 数据 currentIndex: chunkIndex, // 当前分片的索引 totalChunks: totalChunks, // 总分片数 fileName: this.fileName, // 文件名 } } console.log(params) resolve(params); // my.call("ampeHHCommunication", params, res => { // console.log('ampeHHCommunication', res) // console.log(JSON.stringify(res)) // if (res.success) { // resolve(params); // }else{ // reject(JSON.stringify(res)) // } // }); } catch (error) { reject(error) } }); } } // 导出类 module.exports = FileUploader;