文件流转blob对象实现文件下载、预览

文章讲述了如何在前端通过接口接收后端的文件流,实现文件下载功能,并提供了使用Axios处理请求、Blob处理文件类型以及预览功能的代码片段,包括SM2加密解密示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公司最近有个功能需求,是让后端的文件流通过接口返回到前端,前端展示文件,所以记录一下爬坑过程

下载功能封装为download.js文件:

import Axios from "axios";

import {Message} from 'element-ui';

import {doEncrypt,doDecryptStr} from './sm2-1';

//下载文件

export default function download(url,params={},functype){

    return new Promise((resolve)=>{

        getData(url,params,functype).then(res=>{

            const cont=res;

            const data=params;

            const fileTypeArr={

                pdf:"application/pdf;charset=UTF-8", //pdf格式

                doc:"application/msword;charset=UTF-8", //文档格式

                zip:"application/zip;charset=UTF-8", //zip格式

            }

            let fileType=""

            switch(data.fileType){

                case '01':

                    fileType=fileTypeArr.pdf;

                    break;

                case '05':

                    fileType=fileTypeArr.doc;

                    break;

            }

            const header=cont.headers["content-disposition"];

            if(!header) return Message.error({

                message:"下载失败",

                duration:3000

            });

            const stringT=header.split("=")[1]

            const fileName=decodeURI(stringT,"utf-8").replace('.pdf','')

            const blob=new Blob([res.data],{

                type:fileType?fileType:"application/pdf;charset=UTF-8"

            });

            //默认下载功能,没有functype这个参数

            if(!functype){

                if("download" in document.createElement("a")){

                    const link=document.createElement("a");

                    link.download=fileName;

                    link.style.display="none";

                    link.href=URL.createObjectURL(blob);

                    document.body.appendChild(link);

                    link.click();

                    URL.revokeObjectURL(link.href);

                    document.body.removeChild(link);

                    resolve("success");

                }else{

                    navigator.msSaveBlob(blob.fileName);

                }

            }else if(functype=='preview'){

                //functype这个参数传preview则为预览功能

                let herf=URL.createObjectURL(blob);

                this.$store.commit("getPdfUrl",herf);

                this.$router.push({

                    name:"preview",

                    query:{cache:true}

                })

            }

        })

    })

}

//文件下载返回blob数据

function getData(url,params={}){

    return new Promise((resolve,reject)=>{

        Axios({

            url,

            method:"post",

            responseType:"blob",

            headers:{

                "data-token":sessionStorage.getItem('data-token'),

                "Content-Type":"application/json;charset=UTF-8"

            },

            data:{

                data:params.data?doEncrypt(params.data):doEncrypt(JSON.stringify(params))

            }

        }).then(res=>{

            resolve(res);

        }).catch(error=>{

            let url=sessionStorage.getItem('url')

            url=url&&url.replace(/\"/g,"")

            if(error.response.status==401&&url){

                window.location=`${url}`

            }else{

                Message.error({

                    message:`连接出错(${error.response.status})`,

                    duration:3000

                })

            }

            reject('error')

        })

    })

}

在main.js项目入口文件中全局挂载

import download from './utils/download'

Vue.prototype.$download=download

在需要使用的文件中调用,调用方法如下:

this.$download('/xxxx/url',parmas)

this.$download('/xxxx/url',parmas,'preview')

文件预览页preview.vue

<template>

    <div>

        <div class="container" v-loading="loading" @scroll="scroll">

            <pdf ref="pdf" v-for="item in numPages" :key="item" :src="url" :page="item" @loaded="loadPdfHandler"></pdf>

            <el-button type="primary" class="btn" @click="downLoad">下载</el-button>

        </div>

    </div>

</template>

<script>

import pdf from "vue-pdf";

import CMapReaderFactory from "vue-pdf/src/CMapReaderFactory.js";

export default {

    name:"preview",

    components:{

        pdf

    },

    data(){

        return{

            url:"",

            totalPage:undefined,

            numPages:undefined,

            id:"",

            loading:true

        };

    },

    mounted(){

        //获取所需参数

        this.id=this.$store.state.id;

        this.url=this.$store.state.pdfUrl;

        this.getNumPages()

    },

    methods:{

        //动态渲染

        getNumPages(){

            this.$nextTick(()=>{

                let loadingTask=pdf.createLoadingTask(this.url,CMapReaderFactory);

                loadingTask.promis.then(pdf=>{

                    this.numPages=5;//一次渲染五页

                    this.totalPage=pdf.numPages;

                }).catch((err)=>{

                    console.error(err,'pdf加载失败')

                })

            })

        },

        scroll(){

            //滚动渲染

            const el=document.getElementByClassName('container')[0];

            const offsetHeight=el.offsetHeight;

            if(offsetHeight+scrollTop-scrollHeight>=-1){

                if(this.numPages<this.totalPage){

                    this.numPages++

                }

            }

        },

        loadPdfHandler(){

        this.loading=false

        },

        downLoad(){

            let params=JSON.stringify({

                id:this.id

                fileType:"01"

            });

            const data={

                data:params,

            };

            this.download('/xxxx/url',data);

        };

    }

}

</script>

如果有任何问题欢迎沟通交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值