手机型号:iPhone13 Pro Max
IOS 17.6.1
微信版本:8.0.61
基础库版本 3.9.0【1388】
文件分享报错:fail can only be invoked by user TAP gesture.
问题:点击按钮触发开启一个下载任务,然后轮询查看下载任务是否完成,完成后得到url,监听到完成后调用下载并分享
uni.downloadFile({
url: filePath,
filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.xlsx',
success: (res) => {
console.log("downloadRes",res)
if (res.statusCode == 200) {
uni.shareFileMessage({
filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.xlsx',
success:function(openRes){
console.log("successOpenRes",openRes)
uni.hideLoading()
},
fail:function(err){
console.log("failOpenRes",err)
downloadTask.abort()
uni.showToast({
title: '分享失败',
icon: "error"
})
}
})
}

请具体描述问题出现的流程,并提供能复现问题的简单代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)。
刚踩了这个坑,不能用 button , 用 div 标签可以
问题描述:父页面使用了一个自定义封装的下载分享按钮组件。当点击按钮时,开启一个下载任务返回taskId。
开启后父页面调用分享组件的轮询方法:this.$refs.downloadTableButton.pollTask(taskId);
查询下载任务是否完成,完成后触发父页面的onFileReady()方法,onFileReady()里调用downLoadTable(方法),downLoadTable里调用了uni.shareFileMessage,返回错误:errMsg:"shareFileMessage:fail can only be invoked by user TAp gesture.
简单来讲,就是父页面点击按钮后只是开启下载任务,通过监听下载任务完成后自动调用shareFileMessage,该API是否不支持此种操作?
代码片段如下:
父页面使用了下载分享组件UniDownloadTableButton
<template>
<UniDownloadTableButton
v-if="columValue.length > 0"
ref="downloadTableButton"
report-key="chronicleWork"
:download-params=exportParam
//任务开启触发
@download-started="onDownloadStarted"
//任务完成触发,分享操作
@file-ready="onFileReady" />
</template>
</view>
</template>
父页面监听函数:handleDownLoadTable,onDownloadStarted
onDownloadStarted(taskId) { uni.showLoading({ title: '下载中...', mask: true }) // 接收taskId并调用轮询方法 console.log('父组件接收的taskId: ', taskId) if (this.$refs.downloadTableButton) { this.$refs.downloadTableButton.pollTask(taskId); } }, onFileReady(fileData) { // fileData 包含 fileUrl, fileName, isFileReady console.log('文件已准备就绪:', fileData); if (fileData.isFileReady === true && fileData.fileUrl && fileData.fileName) { downLoadTable(fileData.fileUrl, fileData.fileName) } else { uni.showToast({ title: '分享文件失败', icon: 'none' }) } }下载表格函数:downLoadTable
// 下载表格 function downLoadTable( filePath, fileName ) { if (filePath) { const downloadTask = uni.downloadFile({ url: filePath, filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.xlsx', success: (res) => { console.log("downloadRes",res) if (res.statusCode == 200) { uni.shareFileMessage({ filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.xlsx', success:function(openRes){ console.log("successOpenRes",openRes) uni.hideLoading() }, fail:function(err){ console.log("failOpenRes",err) downloadTask.abort() uni.showToast({ title: '分享失败', icon: "error" }) } }) } }, fail:function(err){ uni.hideLoading() console.log('下载文件失败', err) } }) } else { uni.showToast({ title: '暂无数据', icon: 'none' }) } }下载分享组件
<template> <view class="page-bottom-btn position-fixed"> <button @tap="handleDownload" type="primary" class="max-btn-defaut position-fixed__button"> <text class="position-fixed__button--text">将表格分享给好友</text> </button> </view> </template> <script> import { server } from '@/request/server' import {downLoadTable} from "../../../utils/tools"; export default { data() { return { localFileUrl: null, localFileName: null, localIsFileReady: false } }, name: "UniDownloadTableButton", props: { // 报表键值 reportKey: { type: String, default: '' }, // 下载参数(用于自定义下载逻辑) downloadParams: { type: Object, default: () => ({}) }, // 下载方法(可选,用于自定义下载逻辑) downloadMethod: { type: Function, default: null }, // 下载链接 fileUrl: { type: String, default: null }, // 文件名 fileName: { type: String, default: null }, isFileReady: { type: Boolean, default: false } }, methods: { handleDownload() { console.log('下载表格'); console.log(this.reportKey); console.log(this.downloadParams); const params = { reportKey: this.reportKey, params: this.downloadParams } server(`job/execution/start?jobCode=JGB_REPORT_EXPORT`, 'POST',params).then(res => { console.log('异步下载', res) if (res.success && res.data) { const taskId = res.data.id; console.log('任务ID', taskId) if (taskId) { this.$emit('download-started', taskId); } }else{ uni.showToast({ title: res.message, icon: 'none' }) } }) }, // 轮询任务 pollTask(taskId) { console.log('轮询任务', taskId) server(`job/execution/info?jobExecutionId=${taskId}`, 'GET').then(res => { console.log('任务状态', res) if (res.success) { const { jobConfig, progress, stateCode, jobCode, executionResult} = res.data; // FAILED:执行失败,KILLED:已取消,STAGING:启动中,RUNNING:运行中,SUCCEED:执行成功 if (stateCode === 'STAGING' || stateCode === 'RUNNING') { setTimeout(() => { this.pollTask(taskId) }, 1200) }else if (stateCode === 'FAILED') {// 失败 uni.showToast({ title: '下载失败', icon: 'none' }) }else if (stateCode === 'SUCCEED') {// 成功 if (jobConfig.resultDisplayMode === "DOWNLOAD") { // 后端返回下载链接 const { fileName, downloadUrl} = executionResult.data; this.localFileUrl = downloadUrl; this.localFileName = fileName; this.localIsFileReady = true; // 通知父组件更新 fileUrl, fileName 和 isFileReady this.$emit('update:fileUrl', downloadUrl); this.$emit('update:fileName', fileName); this.$emit('update:isFileReady', true); // 触发父组件函数 this.$emit('file-ready', { fileUrl: downloadUrl, fileName: fileName, isFileReady: true }); } } else if (stateCode === 'KILLED') { uni.showToast({ title: '下载失败', icon: 'none' }) } } }); } } } </script> <style scoped> .page-bottom-btn.position-fixed { position: fixed; bottom: 0; left: 0; right: 0; height: 60px; z-index: 10; } .page-bottom-btn.position-fixed .max-btn-defaut.position-fixed__button { background-color: #03BE26 !important; width: 100%; color: #FFFFFF; display: flex; align-items: center; justify-content: center; border-radius: 0; margin: 0; height: 100%; line-height: 60px; font-size: 16px; } .page-bottom-btn.position-fixed .max-btn-defaut.position-fixed__button::after { border: none; } .page-bottom-btn.position-fixed .position-fixed__button--text { font-size: 16px; color: #FFFFFF; } </style>