檔案下載(URL,文件流)

Joanne. ?發表於2019-03-26

根據後臺返回的不同的內容進行檔案下載的方法

1.後臺返回url地址進行下載(.docx /.pptx /.txt /.png /.xls等等)

雖然說用window.open(url)也可以很方便進行檔案的下載,但是下載圖片和txt檔案會變成開啟另外一個頁面,體驗不太友好,所以封裝了以下程式碼,方便各種檔案的下載

course.vue

<template>
    <ul class="view-course-container clear">                    
        <li v-for="(course,courseIndex) in courseList.classArrangeFileList" :key="courseIndex">                        
            <div>                            
                <span :style="`background: url('static/img/${course.img}.png') center center no-repeat;`"></span>                            
                <div>                                
                    <p @click="downloadCourse(course.url,course.name)">{{course.name}}</p>                                
                    <var>{{course.createdTime}}  {{course.createUser}}上傳</var>                            
                </div>                            
                <del @click="deleteFile(course.id)"></del>                        
            </div>                    
        </li>                
    </ul>
</template>
<script>
    export default {
        methods: {
            downloadCourse(url,name) {            
                this.$common.downloadFile(url, name)       
            }
        }
    }
</script>
複製程式碼

common.js

// 下載資源    
downloadFile (url, fileName) {      
    let _this = this      
    let xhr = new XMLHttpRequest()      
    xhr.open('GET', url)      
    xhr.responseType = 'blob'      
    xhr.onload = function () {        
        // 請求完成        
        let blob = this.response        
        console.log(blob)        
        // 建立隱藏的可下載連結        
        let eleLink = document.createElement('a')        
        eleLink.download = fileName        
        eleLink.style.display = 'none'        
        // eleLink.href = url        
        eleLink.href = URL.createObjectURL(blob);        
        // 觸發點選        
        document.body.appendChild(eleLink)        
        eleLink.click()        
        // 然後移除        
        document.body.removeChild(eleLink)      
    }      
    xhr.ontimeout = function(e) {         
        //下載超時請重試        
        console.log(e)        
        // _this.$message.error('下載超時請重試')      
    }      
    xhr.onerror = function(e) {        
        //下載出錯        
        console.log(e)        
        // _this.$message.error('下載出錯,請聯絡管理員')      
    }      
    // 傳送ajax請求      
    xhr.send()    
},複製程式碼



2.後臺返回的文件流前端下載Excel(get請求)

注意點:a標籤下載不要傳token

env.js檔案

import Vue from 'vue'

let baseUrl = 'http://192.168.1.146:8002/ttfs-base-check'; // 測試環境
// 使用者模組ip地址
let userUrl = 'http://192.168.1.146:8002/ttfs-user';  // 測試環境
// 分版本登入地址
Vue.prototype.$loginUrl = "http://192.168.1.146/manage";

export {    
    baseUrl,    
    userUrl
}複製程式碼

score.vue檔案

<template>
    <a :href="excelUrl" class="download-excel">下載Excel</a>
</template>
<script>
    import { baseUrl, userUrl } from '@/config/env';
    export default {
        computed: {
            // excell模板下載地址            
            excelUrl () { 
                //所需的引數               
                let params = {                    
                    kSchoolId: this.kSchoolId,                    
                    kSchoolYearId: this.kSchoolYearId,                    
                    kSemesterId: this.newSemester.id,                    
                    kClassesGroupId: this.classId,                
                }                
                params.scoreClassesGroupId = this.tableFirstId;                
                if(this.orderCodeNum != -1) {                    
                    params.orderCode = this.orderCodeNum;                
                }                
                if(this.courseRankIndex != -1) {                    
                    params.kCourseId = this.scoreCourseId;                
                }
                //地址拼接
                let url = `${baseUrl}/api/score/classes/group/export`;                
                url += '?'                
                for(const item in params){     
                    //encodeURIComponent() 函式可把字串作為 URI 元件進行編碼               
                    url += encodeURIComponent(item) + '=' + encodeURIComponent(params[item]) + '&';                
                };                                
                return url            
            },
        }
    }
</script>複製程式碼


以上的方式雖然簡單,但是下載不了的話報錯不友好,會直接跳到一個300的頁面,顯示一段後臺返回的報錯資訊,所以我又把它優化了一下,就是以下的樣子

<template>
<div class="report" v.loading.fullscreen="loading" element-loading-text="拼命載入中...">
    <var class="score-analysis-download" @click="downloadExcel" v-if="classInfomation.classType!=undefined&&scoreId.id!==''">下載Excel</var>      
    <a :href="excelUrl" style="display:none" ref="loadA">下載Excel</a>
</div>
</template>
<script>
export default {
    data(){
        return{ 
            loading: true
        }
    },
    methods: {
      downloadExcel(e) {      
        this.loading = true;                
        let params = {              
            kSchoolId: this.kSchoolId,              
            kSchoolYearId: this.kSchoolYearId,              
            kSemesterId: this.newSemester.id,              
            scoreClassesGroupId: this.scoreId.id,              
            orderCode: 1          
        }          
        //行政班id          
        if(this.classInfomation.classType === 1 || this.classInfomation.classType === 6) {              
            params.kClassesGroupId = this.classInfomation.kClassesGroupId          
        }else{              
            params.kClassesGroupId = this.classInfomation.kClassId          
        }          
        this.$ajax.get('/api/score/classes/group/export', params).then(res => {            
            if(res.code == 300) {              
                this.loading = false;              
                this.excelUrl = 'javascript:;';              
                this.$message.error(res.msg);            
            }else{              
                let url = `${baseUrl}/api/score/classes/group/export`;              
                url += '?'              
                for(const item in params){                  
                    url += encodeURIComponent(item) + '=' + encodeURIComponent(params[item]) + '&';              
                };              
                this.excelUrl = url;              
                // e.target.href = url;              
                this.$nextTick(() => {                  
                    this.$refs.loadA.click();                  
                    this.loading = false;              
                })            
            }          
       });     
    }
}
</script>複製程式碼


this.$ajax為封裝的axios程式碼,responseType預設為json格式

get(url, urlData, data = 0) {        
    this.isUserModel(url);        
    // 建立一個promise物件        
    // let data=JSON.stringify(datas);        
    // if(data==undefined){        
        this.promise = new Promise((resolve, reject) => {            
            if (data == 0) {                
                url += '?';                
                for (const item in urlData) {                    
                    // url += '/' + urlData[item];                    
                    // url += '?' +item+'=' +urlData[item];                    
                    url += item + '=' + urlData[item] + '&';                
                };            
            } else if (data == 1) {                
                for (const item in urlData) {                    
                    url += '/' + urlData[item];                    
                    // url += '?' +item+'=' +urlData[item];                
                };            
            }
            
        axios.get(url).then((res) => {                
            // debugger                
            if (this._isStatus(res.data)) {                    
                resolve(res.data);                    
                this.countlyMonitorResponse(url);                
            }            
        }).catch((err) => {                
            // console.log(err);                
            // Message.error(err);            
        })        
    })
        
    return this.promise;    
};複製程式碼


3.後臺返回的文件流前端下載Excel(post請求)

當後臺給的請求方法為post時,就不能直接用a標籤新增地址來下載檔案了,需要post請求介面,此時就需要用到另外一種方法,就是把後臺返回的responseType


格式檔案轉化為arraybuffer二進位制流檔案,然後動態建立一個a標籤來下載

<template>
    <div class="score">
        <span class="download-excel">下載Excel</span>
    </div>
</template>
<script>
    import {mapState,mapMutations} from 'vuex'
    export default {
        name: 'scorePage',
        data(){
            return {
                kSchoolId: this.$common.getSession("userData").school.id,                
                kSchoolYearId: this.$common.getSession("userData").schoolYear.id,classId: '123',
            }
        },
        computed:{
            ...mapState('semester',['newSemester']),
        },
        methods: {
            // 下載excel表格            
            downloadExcel() {                
                let params = {                    
                    kSchoolId: this.kSchoolId,                    
                    kSchoolYearId: this.kSchoolYearId,                    
                    kSemesterId: this.newSemester.id,                    
                    kClassesGroupId: this.classId,                
                }                
                params.scoreClassesGroupId = this.tableFirstId;                
                if(this.orderCodeNum != -1) {                    
                    params.orderCode = this.orderCodeNum;                
                }                
                if(this.courseRankIndex != -1) {                    
                    params.kCourseId = this.scoreCourseId;                
                }                
                let url = `${baseUrl}/api/score/classes/group/export`;                
                url += '?'                
                for(const item in params){                    
                    url += encodeURIComponent(item) + '=' + encodeURIComponent(params[item]) + '&';                
                };                
                // responseType: "arraybuffer"將後臺返回的預設json改為二進位制                
                axios.post(url,{responseType: "arraybuffer"}).then(res=>{                    
                    let result = res.data;                    
                    let url =  window.URL.createObjectURL(new Blob([result]));//處理文件流                    
                    // let fileTye = url.match(/.+\/(.+)$/)[1];                    
                    let link = document.createElement('a');                    
                    link.style.display = 'none';                    
                    link.href = url;
                    
                    // link.download = fileTye;                    
                    link.download = '成績彙總表.xls';                    
                    document.body.appendChild(link);                    
                    link.click();   
                    document.body.removeChild(link);             
                })            
            }
        }
    }
</script>複製程式碼

此方法並不侷限於post請求,get請求也一樣可以


最後,分享篇關於匯入二進位制流檔案的文章

zhuanlan.zhihu.com/p/51941539?…  


JS前端建立html或json檔案並瀏覽器匯出下載

www.zhangxinxu.com/wordpress/2…


相關文章