uniapp开发微信小程序实现文件分享及预览功能(带进度条)

<template>
    <view class="card_box">
        <view class="card_body" @tap="toFileReport">
            <view class="data">
                <view class="title"> {{ item.name }} </view>
                <view class="text">备注:{{ item.remark}}</view>
            </view>
            <view class="state">
                <view
                    class="report"
                >
                    {{ item.status }}
                </view>
                <view class="line">
                    <u-icon name="arrow-right"></u-icon>
                </view>
            </view>
        </view>
        <view class="progress-container" v-if="isShowProgress">
            <view class="progress-box">
                <view class="text">文件下载中,请稍后......</view>
                <progress
                    style="margin-bottom: 10px"
                    :percent="progress"
                    show-info
                    stroke-width="3"
                />
                <u-button
                    type="primary"
                    shape="circle"
                    text="取消下载"
                    size="small"
                    @tap="cancelDownload"
                ></u-button>
            </view>
        </view>
    </view>
</template>

<script>
import { openPdfFileByBusKey } from '具体的接口文件路径'
export default {
    data() {
        return {
            injectData: '',
            isShowProgress: false,
            progress: 0,
            isCancelling: false,
            // 添加一个防抖动的定时器
            cancelDebounceTimer: null,
            downloadTask: null // 添加下载任务对象
        }
    },
    props: {
        item: {
            type: Object,
            default: () => ({})
        }
    },
    methods: {
        cancelDownload() {
            if (this.cancelDebounceTimer) {
                clearTimeout(this.cancelDebounceTimer)
            }
            this.cancelDebounceTimer = setTimeout(() => {
                if (this.downloadTask && !this.isCancelling) {
                    this.isCancelling = true
                    this.downloadTask.abort()
                    this.downloadTask = null
                    // 延迟更新状态,确保取消操作完成
                    setTimeout(() => {
                        this.isShowProgress = false
                        this.progress = 0
                        uni.showToast({
                            title: '下载已取消',
                            icon: 'none'
                        })
                        this.isCancelling = false
                    }) // 延迟100毫秒更新状态
                } else if (!this.isCancelling) {
                    this.isShowProgress = false
                    this.progress = 0
                    uni.showToast({
                        title: '没有正在进行的下载',
                        icon: 'none'
                    })
                }
            }, 300) // 防抖动时间设置为300毫秒
        },
        downloadFile(flag) {
            if (this.injectData == '') {
                uni.showToast({
                    title: '文件路径为空',
                    icon: 'none'
                })
                return
            }

            // 获取文件名和类型信息
            const fileInfo = this.parseFilenameAndType(this.injectData)
            const fileName = `${fileInfo.fileName}.${fileInfo.fileType}`

            // 检查文件是否已存在于本地缓存中
            const fileManager = uni.getFileSystemManager()
            const userPath = uni.env.USER_DATA_PATH
            const filePath = `${userPath}/${fileName}`

            try {
                // 尝试获取文件信息,检查文件是否存在
                fileManager.accessSync(filePath)
                // 如果文件存在,直接使用缓存文件
                console.log('文件已存在,直接使用缓存')
                this.handleExistingFile(filePath, fileInfo.fileType, flag)
            } catch (e) {
                // 文件不存在,需要下载
                console.log('文件不存在,开始下载')
                this.downloadAndSaveFile(filePath, fileInfo, flag)
            }
        },

        // 处理已存在的文件
        handleExistingFile(filePath, fileType, flag) {
            let that = this
            if (flag) {
                // 分享到微信
                uni.showModal({
                    title: '提示',
                    content: '确定分享吗?',
                    cancelText: '取消',
                    confirmText: '确定',
                    success: function (res) {
                        if (res.confirm) {
                            const result = that.parseFilenameAndType(
                                that.injectData
                            )
                            uni.shareFileMessage({
                                filePath: filePath,
                                fileType: fileType,
                                fileName: `${result.fileName}.${result.fileType}`,
                                success: () => {
                                    console.log('分享文件成功')
                                },
                                fail: (err) => {
                                    uni.showToast({
                                        title: '分享文件失败',
                                        icon: 'none'
                                    })
                                }
                            })
                        } else if (res.cancel) {
                            console.log('用户点击取消')
                        }
                    }
                })
            } else {
                // 打开文档预览
                uni.openDocument({
                    filePath: filePath,
                    fileType: fileType,
                    showMenu: true,
                    success: (sus) => {
                        console.log('成功打开')
                    },
                    fail: (err) => {
                        uni.showToast({
                            title: '文件打开失败',
                            icon: 'none'
                        })
                    }
                })
            }
        },

        // 下载并保存文件
        downloadAndSaveFile(targetFilePath, fileInfo, flag) {
            let that = this
            this.downloadTask = uni.downloadFile({
                url: this.injectData.replace(/\\/g, '/'), // 下载url
                success: (res) => {
                    if (res.statusCode === 200) {
                        // 直接保存到指定路径,而不是使用系统临时路径
                        uni.getFileSystemManager().saveFile({
                            tempFilePath: res.tempFilePath,
                            filePath: targetFilePath,
                            success: function (red) {
                                that.isShowProgress = false
                                that.handleExistingFile(
                                    targetFilePath,
                                    fileInfo.fileType,
                                    flag
                                )
                            },
                            fail: function (err) {
                                that.isShowProgress = false
                                uni.showToast({
                                    title: '文件保存失败!',
                                    icon: 'none'
                                })
                                console.error('文件保存失败', err)
                            }
                        })
                    } else {
                        that.isShowProgress = false
                        uni.showToast({
                            title: '文件下载失败!',
                            icon: 'none'
                        })
                    }
                },
                fail: (err) => {
                    that.isShowProgress = false
                    uni.showToast({
                        title: '文件下载失败!',
                        icon: 'none'
                    })
                    console.error('下载失败', err)
                }
            })

            this.downloadTask.onProgressUpdate((res) => {
                if (res.progress > 0) {
                    this.isShowProgress = true
                }
                this.progress = res.progress
                // console.log('下载进度:' + res.progress)
                // console.log('已下载长度:' + res.totalBytesWritten)
                // console.log('文件总长度:' + res.totalBytesExpectedToWrite)
            })
        },
        parseFilenameAndType(filePath) {
            // 获取文件名称(包括扩展名)
            const fileNameWithExtension = filePath.split('/').pop()

            // 分离文件名称和扩展名
            const fileNameParts = fileNameWithExtension.split('.')
            const fileName = fileNameParts
                .slice(0, fileNameParts.length - 1)
                .join('.')
            const fileType = fileNameParts[fileNameParts.length - 1]

            return {
                fileName: fileName,
                fileType: fileType
            }
        },
        toFileReport() {
            if (!this.item.busKey) {
                uni.showToast({
                    title: '暂无文件',
                    icon: 'none'
                })
                return
            }
            openPdfFileByBusKey({
                busKey: this.item.busKey
            }).then((res) => {
                this.injectData = res.data.result
                    ? JSON.parse(res.data.result).path
                    : ''

                this.$nextTick(() => {
                    this.downloadFile()
                })
            })
        }
    }
}
</script>

<style lang="scss" scoped>
.card_box {
    margin: 20upx 0;
    padding: 20upx;
    background-color: #fff;
    border-radius: 12upx;
    .card_body {
        display: flex;
        justify-content: space-between;

        .data {
            width: 75%;
            height: 100%;
            display: flex;
            flex-direction: column;

            view {
                flex: 1;
                padding: 10upx 0;
            }

            .title {
                white-space: nowrap; // 使文本不换行显示
                overflow: hidden;
                text-overflow: ellipsis; // 显示省略号
            }

            .text {
                color: #999999;
                font-size: 26upx;
                white-space: nowrap; // 使文本不换行显示
                overflow: hidden;
                text-overflow: ellipsis; // 显示省略号
            }
        }

        .state {
            width: 15%;
            height: 100%;
            text-align: right;
            display: flex;
            flex-direction: column;

            .color {
                color: #ff7a00;
            }

            .report {
                padding: 10upx 0;
            }

            .line {
                flex: 1;
                height: 100%;
                display: flex;
                justify-content: flex-end;
                align-items: center;
                margin-top: 160upx;
            }
        }
    }

    .card_action {
        display: flex;
        justify-content: flex-end;
        align-items: center;
        padding: 10upx 0;
    }
}

.customStyle {
    width: 170upx;
    margin: 0 10upx;
}

.progress-container {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 99;
    background: rgba(0, 0, 0, 0.2);
    width: 750rpx;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;

    .progress-box {
        background: #ffffff;
        border-radius: 20rpx;
        padding: 30rpx;

        .text {
            margin-bottom: 20rpx;
        }
    }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值