背景
前端: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文件打开时报错,但是在服务器端保存的文件打开是正常的
尝试了很多方法没有解决。但因为后端实现最初的请求是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