收藏
回答

wx.shareFileMessage异步调用报错fail can only be invoked?

手机型号: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"
          })               
        }
      })
    }



回答关注问题邀请回答
收藏

3 个回答

  • 社区技术运营专员--阳光
    社区技术运营专员--阳光
    2025-08-05

    请具体描述问题出现的流程,并提供能复现问题的简单代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)。

    2025-08-05
    有用
    回复
  • Eddy
    Eddy
    2025-09-01

    刚踩了这个坑,不能用 button , 用 div 标签可以

    2025-09-01
    有用
    回复
  • 有志不在年糕
    有志不在年糕
    2025-08-05

    问题描述:父页面使用了一个自定义封装的下载分享按钮组件。当点击按钮时,开启一个下载任务返回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>
    


    2025-08-05
    有用
    回复
登录 后发表内容