vue实现文档下载
使用 <a> 标签下载
通过动态生成 <a> 标签并触发点击实现下载。适用于直接下载静态文件或后端返回的二进制流。
// 方法1: 直接下载静态文件
const downloadByLink = (url, filename) => {
const link = document.createElement('a')
link.href = url
link.download = filename || 'document'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
// 使用示例
downloadByLink('/files/report.pdf', '季度报告.pdf')
处理 Blob 数据下载
当后端返回二进制流(如 Blob 数据)时,需先转换为可下载的 URL。
const downloadBlob = (blobData, fileName) => {
const url = window.URL.createObjectURL(blobData)
const link = document.createElement('a')
link.href = url
link.download = fileName
link.click()
window.URL.revokeObjectURL(url) // 释放内存
}
// 结合axios示例
axios.get('/api/download', {
responseType: 'blob'
}).then(res => {
downloadBlob(res.data, 'export.xlsx')
})
文件流下载处理
针对后端返回文件流的情况,需设置正确的响应类型和响应头解析。
axios({
method: 'get',
url: '/api/export',
responseType: 'blob',
}).then(response => {
const contentDisposition = response.headers['content-disposition']
const fileName = decodeURIComponent(
contentDisposition.match(/filename=(.*?)(;|$)/)[1]
)
const blob = new Blob([response.data])
const downloadUrl = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = downloadUrl
a.download = fileName
a.click()
URL.revokeObjectURL(downloadUrl)
})
封装为 Vue 指令
可复用逻辑可封装为全局指令,通过 v-download 调用。
// main.js 全局注册
Vue.directive('download', {
bind(el, binding) {
el.addEventListener('click', () => {
const { url, filename } = binding.value
const link = document.createElement('a')
link.href = url
link.download = filename || 'download'
link.click()
})
}
})
// 组件中使用
<button v-download="{ url: '/file.doc', filename: '合同.doc' }">
下载文档
</button>
注意事项
- 跨域问题需确保服务器配置
Access-Control-Allow-Origin - 大文件下载建议显示进度条,可通过
axios的onDownloadProgress实现 - 后端应设置正确的
Content-Disposition响应头 - 移动端部分浏览器可能限制自动下载,需用户主动触发
完整组件示例
<template>
<div>
<button @click="handleDownload">下载PDF</button>
<button @click="handleExport">导出Excel</button>
</div>
</template>
<script>
export default {
methods: {
handleDownload() {
this.$axios.get('/file.pdf', {
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data])
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'document.pdf'
link.click()
})
},
handleExport() {
this.$axios.get('/api/export', {
responseType: 'blob',
onDownloadProgress: progressEvent => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
console.log(`下载进度: ${percent}%`)
}
}).then(res => {
const fileName = res.headers['content-disposition']
.split('filename=')[1]
.replace(/"/g, '')
const url = window.URL.createObjectURL(res.data)
const link = document.createElement('a')
link.href = url
link.download = fileName
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
}
}
}
</script>






