3***@qq.com
3***@qq.com
  • 发布:2025-10-27 14:16
  • 更新:2025-10-27 14:16
  • 阅读:14

分片上传、文件分片,使用Html5Plus API。测试对比MD5。

分类:uni-app

兄弟们,我在看掘金的时候找到分片上传失败的原因了,就很小的一个点:

html5Plus 的文档写的不太清楚出了,很多地方让人猜。就比如File.slice(start,end) ,在js中slice截取不包含end,但在Html5Plus File.slice包含end,导致合并文件后总是比原文件大一点

也就是使用Html5Plus的File.slice方法:每个分片end-1
已经在安卓模拟器上测试,并对比MD5值。

因为没有 readAsArrayBuffer 方法,只能通过 Base64 转 ArrayBuffer,需要注意去除dataUrl头部
关键代码

const readFileChunk = (file, start, end) => {  
    return new Promise((resolve, reject) => {  
        try {  
            const reader = new plus.io.FileReader();  
            reader.onload = () => {  
                try {  
                    // 排除base64头部  
                    const base64 = reader.result.substring(reader.result.indexOf(',')   1);  
                    resolve(uni.base64ToArrayBuffer(base64));  
                } catch (e) {  
                    reject(e)  
                }  
            };  
            reader.onerror = reject;  

            // 使用slice方法读取指定范围, 需要注意: end 包含  
            const blob = file.slice(start, end);  
            reader.readAsDataURL(blob); // HTML5 需要转换为base64读取  
        } catch (e) {  
            reject(e)  
        }  
    });  
};

完整的分片上传

    async uploadMultipart(filePath, chunkSize = 1024 * 1024 * 5) {  

        // 通过文件路径获取File对象(Html5Plus的File)  
        const file = await getFile(filePath);  
        const uploadId = await multipartUploadApi.startMultipart(file.name)  
        // console.log('uploadId', uploadId)  

        const partList = []  
        const totalSize = file.size;  
        for (let i = 0; i < totalSize / chunkSize; i  ) {  
            const start = i * chunkSize;  
            const end = Math.min((i   1) * chunkSize - 1, totalSize);  
            const chunkBuffer = await readFileChunk(file, start, end);  
            const partItem = await multipartUploadApi.uploadPart(uploadId, i   1, chunkBuffer)  
            partList.push(partItem)  
        }  
        const result = await multipartUploadApi.complete(uploadId, partList)  

        return result  
    },  

    getFile(filePath) {  
        return new Promise((resolve, reject) => {  
            plus.io.resolveLocalFileSystemURL(filePath, (entry) => {  
                if (!entry.isFile) {  
                    reject(new Error(`不是文件:${filePath}`))  
                    return  
                }  
                entry.file((file) => {  
                    resolve(file)  
                }, (err) => {  
                    // console.log('无法获取文件')  
                    reject(err)  
                })  
            }, (error) => {  
                // console.log('文件不存在', error)  
                reject(error)  
            })  
        })  
    },  
  readFileChunk (file, start, end) {  
    return new Promise((resolve, reject) => {  
        try {  
            const reader = new plus.io.FileReader();  
            reader.onload = () => {  
                try {  
                    // 排除base64头部  
                    const base64 = reader.result.substring(reader.result.indexOf(',')   1);  
                    resolve(uni.base64ToArrayBuffer(base64));  
                } catch (e) {  
                    reject(e)  
                }  
            };  
            reader.onerror = reject;  

            // 使用slice方法读取指定范围, 需要注意: end 包含  
            const blob = file.slice(start, end);  
            reader.readAsDataURL(blob); // HTML5 需要转换为base64读取  
        } catch (e) {  
            reject(e)  
        }  
    });  
};

参考的掘金文章:
解决Uniapp中文件切片问题
作者:Synmbrf
链接:https://juejin.cn/post/7493783786707058726
来源:稀土掘金

0 关注 分享

要回复文章请先登录注册