我爱模板网采用UniApp 实现 PDF 文件下载(二进制)、保存与查看功能(兼容Android、IOS、H5)的方法,实现后端返回二进制流下载、保存并打开pdf和xlsx文件的时候,打开文件报错了:fail not found 3th activity,没有找到对应的第三方软件来打开。尽管这个文件没有后缀,并且openDocument也指定了fileType为xlsx。
在uni.downloadFile的success回调方法中,打印了一下临时文件在手机中的路径。
plus.io.convertLocalFileSystemURL(res.tempFilePath)
在手机目录中查看的时候,这个文件是一个BIN文件(我的是JSON文件),但是网页浏览器访问下载的时候,是一个xlsx文件。而且,也正是需要展示这个类型的文件。后面调用uni.openDocument方法打开文件时也总是打开失败。
只能通过更改文件名称来解决这个办法。
// 拿到临时文件的绝对路径 let filepathss=plus.io.convertLocalFileSystemURL(res.tempFilePath); // 通过这个路径来拿到他 plus.io.resolveLocalFileSystemURL(filepathss,function(entry){ const tempFileName = entry.name; entry.getParent(function (parentDicEntry) { console.log(parentDicEntry.fullPath) entry.moveTo({ fullPath: parentDicEntry.fullPath+'/'},'新的文件名字.xlsx',function (newFile) { uni.openDocument({ fileType: 'xlsx', filePath: newFile.fullPath, success: function (res2) { console.log('打开文档成功'); }, fail: function (err) { if(err.errCode == 1 || err.code == 1){ uni.showToast({ title: `未找到能打开xlsx类型文件的手机应用`, icon: 'none' }) } console.log(err) } }); },function(moveError){ uni.showToast({ title: `已在第三方应用中打开过,请在第三方应用查看时保存`, icon: 'none' }) }) }) })
上面这个方法并没有改变文件的路径,放在了相同的路径下面,取了一个新的名称。但是这个方法有一个问题,因为这个路径下面保存的是临时文件,在我本地手机上测试的时候,第二次调用接口去下载的时候,会进入到moveTo的errorCB回调方法中。于是我只能提示这个文件在第三方应用中打开过。
因为是临时文件,在退出app重新打开的时候,再次下载还是没问题的。
最终代码(支持pdf和xlsx格式)
function doExport(type) { let Authorization = '' let userInfo = uni.$store.state.userInfo || uni.getStorageSync('userInfo') if (userInfo?.access_token) { Authorization = 'Bearer ' + userInfo.access_token } let header = {}; if (Authorization) { header['Authorization'] = Authorization; } let clientId = import.meta.env.VITE_MP_APP_CLIENT_ID // #ifdef APP-PLUS if (plus.os.name === 'iOS') { clientId = import.meta.env.VITE_IOS_APP_CLIENT_ID } else if (plus.os.name === 'Android') { clientId = import.meta.env.VITE_ANDROID_APP_CLIENT_ID } // #endif header['clientid'] = clientId uni.downloadFile({ url: uni.$api.exportTaskEmployedUsers().url + '?taskId=' + searchForm.taskId + '&exportType=' + type, header, responseType: "blob", success: (res) => { if (res.statusCode === 200) { console.log("res", res); // 拿到临时文件的绝对路径 let filepathss = plus.io.convertLocalFileSystemURL(res.tempFilePath); // 通过这个路径来拿到他 plus.io.resolveLocalFileSystemURL(filepathss, function(entry) { const tempFileName = entry.name; entry.getParent(function(parentDicEntry) { console.log(parentDicEntry.fullPath) entry.moveTo({fullPath: parentDicEntry.fullPath + '/'}, `已录用兼职工名单-${uni.$app.formatDate3()}.${type === 1 ? 'xlsx' : 'pdf'}`, function(newFile) { uni.saveFile({ tempFilePath: newFile.fullPath, success: (saveRes) => { console.log("文件保存路径:", saveRes.savedFilePath); // 在app端执行 // #ifdef APP-PLUS let osname = plus.os.name; // 如果是安卓的话弹出提示 if (osname == "Android") { uni.$app.showToast("下载并保存成功,即将打开文件~"); } // #endif //ios手机直接打开文件,手动存储文件到手机,Android手机从根目录创建文件夹,保存文件并改名 setTimeout(() => { //打开文档查看 uni.openDocument({ fileType: 'xlsx', filePath: newFile.fullPath, success: function(res2) { console.log('打开文档成功'); }, fail: function(err) { if (err.errCode == 1 || err.code == 1) { uni.showToast({ title: `未找到能打开xlsx类型文件的手机应用`, icon: 'none' }) } console.log(err) } }); }, 1000); }, fail: (err) => { uni.$app.showToast("保存失败"); console.error("保存文件失败:", err); } }); }, function(moveError) { uni.showToast({ title: `已在第三方应用中打开过,请在第三方应用查看时保存`, icon: 'none' }) }) }) }) } else { uni.$app.showToast("下载失败"); console.error("下载文件失败,状态码:", res.statusCode); } }, fail: (err) => { uni.$app.showToast("下载失败"); console.error("下载文件失败:", err); } }) }