vue+elementui实现文件下载和进度条显示

html
<template>
		<el-button @click="getProgress">点击下载</el-button>
	<!-- 文件下载进度条 -->
        <el-dialog title="正在下载,请等待" :visible.sync="progressShow" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false" width="20%">
            <div style="text-align: center;">
                <el-progress :percentage="percentage" type="circle"></el-progress>
            </div>
        </el-dialog>
</template>
<script >
	export default {
		data() {
			return {
				percentage:0, //进度条的占比
                progressShow: false, // 是否显示进度条弹出层
			}
		},
		methods: {
			// 下载文件进度条
            getProgress(url='http://192.168.1.111/tpdemo/public/uploads/export_xls.xlsx') {
                //进度条恢复为 0 
                this.percentage= 0;
                //发起请求
                this.$axios({
                    url: url,
                    method:"get",
                    responseType:"blob",
                    params:{},
                    //xml返回数据的钩子函数,可以用来获取数据的进度 具体可查看axios的官网
                    onDownloadProgress:(progressEvent)=>{
                        //progressEvent.loaded 下载文件的当前大小
                        //progressEvent.total  下载文件的总大小 如果后端没有返回 请让他加上!
                        let progressBar = Math.round( progressEvent.loaded / progressEvent.total*100);
                        //接收进度为99%的时候需要留一点前端编译的时间
                        if(progressBar >= 99){
                            this.percentage = 99;
                            this.$message.success("下载完成,文件正在编译。");
                            // this.title = '下载完成,文件正在编译。';
                        }else{
                            this.percentage = progressBar;
                            this.$message("正在下载,请稍等。");
                            // this.title = '正在下载,请稍等。';
                        }
                        // console.log(progressEvent)
                    }
                }).then(res => {
                    // console.log(res)
                    if(res.status != 200){
                        this.$message.error("文件下载失败,请稍后重试!");
                        return false;
                    }
                    //blob返回的是一个 base64 格式的文件流
                    let blob = new Blob([res.data],{
                        //编译文件为xlsx类型。 具体可查看 blob 方法定义的类型 
                        type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                    })
                    //编译文件
                    if(window.navigator && window.navigator.meSaveOrOpenBlob){
                        window.navigator.meSaveOrOpenBlob(blob,"文件名称.xlsx")
                    }else{
                        // 非ie的下载
                        const link = document.createElement('a');
                        const body = document.querySelector('body');
                        link.href = window.URL.createObjectURL(blob);
                        link.download = '年检年报查询_'+new Date().getTime(); // 下载的文件名
                        // fix Firefox
                        link.style.display = 'none';
                        body.appendChild(link);
                        link.click();
                        body.removeChild(link);
                        window.URL.revokeObjectURL(link.href);
                    }
                    //编译文件完成后,进度条展示为100%100
                    this.percentage =100;
                    this.progressShow = false; // 关闭进度条显示层

                })
            },
		}
	}
</script>

参考:https://blog.csdn.net/zzz305379801/article/details/121029937

下载的excl文件,内容显示object,object:https://blog.csdn.net/qq_36873710/article/details/123270166

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue+elementui分片上传可以使用如下步骤: 1. 前端将大文件分为若干个片段,并将每个片段上传到后端。 2. 后端将每个片段存储在服务器上,并返回每个片段的文件名和存储路径。 3. 前端将每个片段的文件名和存储路径组成一个数组,发送给后端。 4. 后端将数组中的每个片段按照顺序合并成一个完整的文件。 5. 前端可以在上传过程中显示上传进度,并支持暂停、恢复和取消上传。可以使用Vue+elementui+axios实现文件分片上传。 以下是示例代码: ``` <template> <div> <el-upload ref="upload" :show-file-list="false" :on-change="handleChange" :before-upload="handleBeforeUpload" :on-progress="handleProgress" :on-success="handleSuccess" :on-error="handleError"> <el-button size="small" type="primary">点击上传</el-button> </el-upload> <el-progress :percentage="percent"></el-progress> <el-button-group> <el-button size="small" @click="handleStart">开始上传</el-button> <el-button size="small" @click="handlePause">暂停上传</el-button> <el-button size="small" @click="handleResume">恢复上传</el-button> <el-button size="small" @click="handleCancel">取消上传</el-button> </el-button-group> </div> </template> <script> import { ElUpload, ElButton, ElProgress, ElButtonGroup } from 'element-ui' import axios from 'axios' export default { components: { ElUpload, ElButton, ElProgress, ElButtonGroup }, data() { return { file: null, fileChunks: [], uploading: false, uploadedChunks: [], percent: 0, uploadUrl: 'https://www.example.com/upload', token: 'your_token', fileId: 'your_file_id', chunkSize: 1024 * 1024, // 每个片段的大小 maxRetries: 5, // 最大重试次数 } }, methods: { handleChange(file) { this.file = file this.fileChunks = this.getChunks(file) this.uploadedChunks = [] this.percent = 0 }, handleBeforeUpload(file) { // 阻止自动上传 return false }, handleStart() { if (!this.uploading) { this.uploading = true this.uploadChunks(this.fileChunks, 0) } }, handlePause() { this.uploading = false }, handleResume() { this.uploading = true this.uploadChunks(this.fileChunks, this.uploadedChunks.length) }, handleCancel() { this.file = null this.fileChunks = [] this.uploading = false this.uploadedChunks = [] this.percent = 0 }, handleProgress(event, file) { if (file === this.file) { this.percent = event.percent } }, handleSuccess(response, file) { if (file === this.file) { this.uploading = false console.log('上传成功') } }, handleError(error, file) { if (file === this.file) { this.uploading = false console.log('上传失败') } }, getChunks(file) { const fileSize = file.size const chunks = [] let start = 0 let end = this.chunkSize while (start < fileSize) { chunks.push({ file: file.slice(start, end), index: Math.ceil(start / this.chunkSize), retries: 0, uploaded: false, uploading: false, error: false, }) start = end end += this.chunkSize } return chunks }, async uploadChunks(chunks, start) { if (!this.uploading) { return } const maxIndex = chunks.length - 1 for (let i = start; i <= maxIndex; i++) { const chunk = chunks[i] if (chunk.uploaded || chunk.uploading) { continue } chunk.uploading = true const formData = new FormData() formData.append('chunkIndex', chunk.index) formData.append('chunkFile', chunk.file) formData.append('chunkSize', this.chunkSize) formData.append('fileId', this.fileId) formData.append('token', this.token) try { const response = await axios.post(this.uploadUrl, formData, { headers: { 'Content-Type': 'multipart/form-data', }, }) chunk.uploaded = true chunk.uploading = false this.uploadedChunks.push(chunk) console.log(`上传成功:${chunk.index}`) } catch (error) { chunk.uploading = false if (chunk.retries < this.maxRetries) { chunk.retries++ console.log(`上传失败,正在重试:${chunk.index}`) i-- } else { chunk.error = true console.log(`上传失败:${chunk.index}`) } } if (this.uploadedChunks.length === chunks.length) { this.mergeChunks(chunks) break } } }, async mergeChunks(chunks) { const formData = new FormData() formData.append('fileId', this.fileId) formData.append('token', this.token) try { const response = await axios.post(this.uploadUrl + '/merge', formData) console.log('合并成功') } catch (error) { console.log('合并失败') } }, }, } </script> ``` 以上代码中,`el-upload`组件用于选择文件显示上传进度,`ElProgress`组件用于显示上传进度条,`ElButtonGroup`组件用于控制上传操作。`handleChange`方法用于获取文件,并将文件分成若干个片段。`handleBeforeUpload`方法用于阻止自动上传。`handleStart`方法用于开始上传。`handlePause`方法用于暂停上传。`handleResume`方法用于恢复上传。`handleCancel`方法用于取消上传。`handleProgress`方法用于更新上传进度。`handleSuccess`方法用于上传成功后的处理。`handleError`方法用于上传失败后的处理。`getChunks`方法用于将文件分成若干个片段。`uploadChunks`方法用于上传每个片段。`mergeChunks`方法用于将所有片段合并成一个完整的文件。 注意,在上传每个片段时,需要使用`FormData`来上传文件。在上传成功后,需要将上传成功的片段保存在`uploadedChunks`数组中,并在所有片段都上传成功后,调用`mergeChunks`方法将所有片段合并成一个完整的文件。在上传过程中,可以使用`percent`属性来显示上传进度。在上传时,可以支持暂停、恢复和取消上传操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值