Flask+Vue實現excel文件從服務器端導出至本地


背景

前端:Vue
后端:Flask-Restful

這里主要實現的功能是將數據庫中的數據整理后寫入Excel文件,並先將文件存儲在服務器端,再在客戶端將文件從服務器端下載到本地。
雖然后端主要是用的Flask-Restful,但這里導出的實現還是使用的Flask中的send_from_directory,因為在Flask-Restful中沒有找到合適的方法實現

后端

@app.route("/api/v1/Services/Download/<string:product_flag>&&<string:product_version>", methods=['POST'])
def downloader(product, product_version):
    filename = data_output(product, product_version)  # data_output方法實現數據庫中的數據寫入Excel文件,返回文件名

    dir_path = str(os.path.abspath(os.path.dirname(__file__)))
    dirpath = os.path.join(os.path.join(dir_path, 'downloads'))  # 獲取文件路徑

    response = make_response(send_from_directory(dirpath, filename, as_attachment=True))
    response.headers["Access-Control-Expose-Headers"] = "Content-disposition"

    return response

前端

按鈕,點擊調用方法handleDownload

<el-button v-waves :loading="downloadLoading" class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-download" @click="handleDownload">
   導出
</el-button>

js方法實現

handleDownload() {
      axios.post(
        this.downloadUrl + this.listQuery.product + '&&' + this.listQuery.product_version,
        { responseType: 'arraybuffer' }
      ).then(response => {
        if (response.status === 200) {
          const blob = new Blob([response.data], {
            type: response.headers['content-type']
          })

          const fileName = response.headers['content-disposition']
          const title = fileName && (fileName.indexOf('filename=') !== -1) ? fileName.split('=')[1].split('; filename')[0] : 'download'
          require('script-loader!file-saver')
          saveAs(blob, title)
        }
      }).catch()
    }

問題解決

導出的excel文件打開時報錯,但是在服務器端保存的文件打開是正常的
image
嘗試了很多方法沒有解決。但因為后端實現最初的請求是GET,所以我在想將請求換回GET,重新寫前端邏輯是否可行,沒想到真的解決了這個問題。先貼代碼

handleDownload() {
      axios.get(
        this.downloadUrl + this.listQuery.product + '&&' + this.listQuery.product_version,
        { responseType: 'blob' }
      ).then(response => {
        if (!response) {
          return
        }
        const filename = response.headers['content-disposition'].split('filename=')[1].split('; filename')[0]
        const url = window.URL.createObjectURL(response.data)
        const link = document.createElement('a')
        link.style.display = 'none'
        link.href = url
        link.setAttribute('download', '導出' + filename)
        document.body.appendChild(link)
        link.click()
      }).catch()
    }

使用了axios的get方法,其中請求的responseType為blob,而非arraybuffer


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM