问题背景
对于一个txt文本、图片、视频、音频等浏览器可以直接使用浏览器进行预览的文件,
使用传统的a标签加download属性进行下载是行不通的,会在浏览器直接打开,因此需要搞一个新的方式进行下载。
实现流程
实现思路
这里使用Vue自定义指令,对文件链接进行处理,将链接转化为blob进行下载,Vue2和Vue3在写法上有所区别。
定义指令
在src目录中,新建存放所有自定义指令的目录directive,然后新建vdown.js并编写指令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import Vue from "vue"; Vue.directive('down', { inserted: (el, binding) => { el.addEventListener('click', () => { let link = document.createElement('a') let url = binding.value fetch(url).then(res => res.blob()).then(blob => { link.href = URL.createObjectURL(blob) console.log(link.href) link.download = '' document.body.appendChild(link) link.click() }) }) } })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let vdown = { mounted: (el, binding) => { el.addEventListener('click', () => { console.log(binding.value) let link = document.createElement('a') let url = binding.value console.log(url) fetch(url).then(res => res.blob()).then(blob => { link.href = URL.createObjectURL(blob) console.log(link.href) link.download = '' document.body.appendChild(link) link.click() }) }) } } export default vdown
|
指令中使用fetch获取文件内容,并转换为blob,然后通过构造的A标签模拟点击进行下载。
注册指令
在Vue2写法中,已经使用Vue.directive
注册了指令,所以直接在main中引入自定义指令的脚本文件即可:
| ... import '@/directive/vdonw' ...
|
而在Vue3写法中,定义指令的脚本中只是定义了指令的内容而未注册,所以需要在main中进行注册:
| import { createApp } from 'vue' import App from './App.vue' var app = createApp(App)
import vdown from '@/directive/vdown' app.directive('down', vdown)
app.mount('#app')
|
使用指令
在Vue文件中,直接定义下载按钮,添加v-down指令并传递要下载的URL,即可完成下载:
| ... <a v-down="'http://127.0.0.1:8888/file.txt'">下载文件</a> ...
|
跨域问题
若遇到跨域问题,配置proxy代理解决即可,在vue.config.js中添加如下内容:
| module.exports = { devServer: { proxy: { '/serverfile': { target: 'http://www.xxx.com', ws: true, changOrigin: true, pathRewrite: { '^/serverfile': '/' } }
} } }
|
修改下载按钮中的连接:
| ... <a v-down="'/serverfile/file.txt'">下载文件</a> ...
|
然后点击下载即可成功下载: