downloadFile.js 5.11 KB

import { downloadFileApi } from '@/api/base.js'
import { getToken } from '@/utils/auth.js'

/**
     * 下载文件通用方法
     * @param id
     * @param fileName
     */
export async function downloadFile(id, fileName) {
    if (!id) return
    uni.showLoading({ title: '下载中' })
    try {
        const res = await downloadFileApi(id);
        console.log('downloadFileApi__res', res)
        let url = res.data
        if (url) {
            // #ifdef H5
            // H5环境(包括微信、钉钉等)直接跳转可能不带header,需要把token拼接到url上
            const token = getToken()
            if (token) {
                const separator = url.includes('?') ? '&' : '?'
                url = `${url}${separator}X-Auth-Token=${token}`
            }
            // #endif

            // 统一使用 uni.downloadFile 下载,解决微信浏览器“在浏览器打开”的提示问题
            uni.downloadFile({
                url,
                success: (res) => {
                    if (res.statusCode === 200) {
                        const filePath = res.tempFilePath

                        // #ifdef H5
                        const ua = navigator.userAgent.toLowerCase()
                        const isAndroid = ua.indexOf('android') > -1 || ua.indexOf('adr') > -1
                        const isWeChat = ua.indexOf('micromessenger') !== -1

                        if (isWeChat && isAndroid) {
                            // 安卓微信环境:提示用户去浏览器下载
                            // 注意:Blob URL在外部浏览器无法访问,所以这里必须使用原始的 url (带token)
                            // 重新构建带token的原始url
                            let downloadUrl = url
                            // 这里我们假设 url 变量在上面已经被处理过(拼接了token),如果没有,重新拼接
                            if (!downloadUrl.includes('X-Auth-Token')) {
                                const token = getToken()
                                if (token) {
                                    const separator = downloadUrl.includes('?') ? '&' : '?'
                                    downloadUrl = `${downloadUrl}${separator}X-Auth-Token=${token}`
                                }
                            }

                            uni.showModal({
                                title: '提示',
                                content: '微信环境下不支持直接下载,请复制链接后在浏览器打开下载',
                                confirmText: '复制链接',
                                showCancel: false,
                                success: function (res) {
                                    if (res.confirm) {
                                        uni.setClipboardData({
                                            data: downloadUrl,
                                            success: function () {
                                                uni.showToast({ title: '链接已复制', icon: 'success' })
                                            }
                                        })
                                    }
                                }
                            })
                        } else {
                            // 其他环境(iOS微信、普通浏览器)使用a标签下载
                            const link = document.createElement('a')
                            link.href = filePath
                            link.download = fileName || 'download'
                            document.body.appendChild(link)
                            link.click()
                            document.body.removeChild(link)
                        }
                        // #endif

                        // #ifndef H5
                        const fileType = fileName ? fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase() : ''
                        uni.openDocument({
                            filePath,
                            fileType: fileType || undefined,
                            showMenu: true,
                            success: function () {
                                console.log('打开文档成功')
                            },
                            fail: function (err) {
                                console.error('打开文档失败', err)
                                uni.showToast({ title: '无法打开此文件', icon: 'none' })
                            }
                        })
                        // #endif
                    } else {
                        uni.showToast({ title: '下载失败', icon: 'none' })
                    }
                },
                fail: (err) => {
                    console.error('下载失败', err)
                    uni.showToast({ title: '下载失败', icon: 'none' })
                }
            })
        } else {
            uni.showToast({ title: '文件地址无效', icon: 'none' })
        }
    } catch (e) {
        console.error(e)
        uni.showToast({ title: '下载出错', icon: 'none' })
    } finally {
        uni.hideLoading()
    }
}