123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- 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;
|