Uniapp webview实现下载文件

84 阅读1分钟

直接上代码, 使用方法: 获得要下载文件的blob, 然后调用doAppDownloadFile. 比如:

const FileBlob: Blob = xxxxx;
doAppDownloadFile(FileBlob, 'a.txt');

// 声明plus全局对象以解决TypeScript类型错误
declare var plus: any;

export async function doAppDownloadFile(dataBlob: Blob, fileName: string){
    const localFilePath = await _doAppDownloadFile(dataBlob, fileName);
    /// 在设备上实际存储的位置
    const actualPath= plus.io.convertLocalFileSystemURL(localFilePath);

    // console.log(localFilePath, actualPath);
    plus.runtime.openFile(localFilePath);
    return actualPath;
}

function _doAppDownloadFile(dataBlob: Blob, fileName: string){
    return new Promise(function(resolve, reject) {
        blobToBase64(dataBlob).then(base64Text=>{
            if (typeof plus === 'object') {
                // 使用公共下载目录
                const fileSystemType = plus.io.PUBLIC_DOWNLOADS;
                let filePath = '';
                
                plus.io.requestFileSystem(fileSystemType, function(fs) {
                    fs.root.getFile(fileName, {
                        create: true,
                        exclusive: false,
                    }, function(entry) {
                        filePath = entry.fullPath;
                            entry.createWriter(function(writer) {
                                writer.onwrite = function() {
                                    // console.log('文件已保存到:', filePath)
                                    resolve(filePath)
                                }
                                writer.onerror = reject
                                writer.seek(0)
                                writer.writeAsBinary(base64Text.replace(/^data:\S+\/\S+;base64,/, ''))
                            }, reject)
                        }, reject)
                }, reject)
            }
        })
    })     
}

export function blobToBase64(blob) {
    return new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(blob);
        //@ts-expect-error
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
    });
}