下载文件方式
web网页中下载文件一般利用a
标签的方式下载,下载依赖浏览器特性,我们一般是通过接口请求返回 URL 链接或者文件流。
给a
标签添加download
属性就有了下载功能。
需要注意的是
download
不支持跨域请求。
使用download
属性,不符合同源策略(下载的文件和你的网站不是在一个域名下),该属性可能会失效,文档、图片等一些可预览文件就触发了浏览器的预览功能,而不是下载。
URL链接下载
download
属性可以不设置值,默认使用链接中的文件名
<a href="./anime-8788959_1280.jpg" download>点击下载</a>
或者给标签绑定点击事件,在 js 中创建 a 标签
const a = document.createElement('a');
a.href = './anime-8788959_1280.jpg';
a.download = 'test.jpg';
a.target = '_blank';
a.click();
文件流下载
需要后端接口配合,调用接口返回文件流,然后再利用a
标签下载。
导出Excel
适用于接口返回文件流的情况
- 定义导出方法
// utils.js
import axios from "axios";
/**
* exportExcel Excel 表格导出
* @param {string} url 请求地址
* @param {object} params 请求参数
* @param {string} exportFileName 导出文件名
* @param {string} service 服务名
*/
export function exportExcel(url, params = {}, exportFileName = "导出数据", service = "_api_vehicle") {
axios.get(url, {
headers:{
'Access-Control-Allow-Origin': '*'
},
params,
responseType: 'blob'
}).then(res => {
if(res.data.type === 'application/json') { // 错误信息处理
console.log(res.data.type)
let reader = new FileReader()
reader.onload = ()=> {
let content = reader.result
let description = JSON.parse(content).description // 错误信息
// TODO 错误处理
Vue.prototype.$Notice.warning({ title: '导出失败', desc: description });
}
reader.readAsText(res.data)
return false
}
// 使用a标签下载
const link = document.createElement('a')
let fileName = ""
let blob = new Blob([res.data], {type: 'application/vnd.ms-excel'})
let url = window.URL.createObjectURL(blob)
link.style.display = 'none'
link.href = url
// 判断响应头里如果返回的有文件名,如果有使用响应头中的文件名
if (!res.headers["content-disposition"]) {
fileName = exportFileName
}else {
fileName = res.headers["content-disposition"]
.split(";")[1]
.split("=")[1]; //filename名称截取
}
// 命名下载名称,文件名需要解码一下
link.download = decodeURIComponent(fileName);
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
// 下载完成进行释放
window.URL.revokeObjectURL(url);
}).catch((err) => {
console.log("导出失败", err)
})
}
- 使用
import { exportExcel } from "@/utils"
export default {
// ...
methods: {
download() {
exportExcel("/download", {}, "导出文件")
}
}
}
URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
createObjectURL()支持传入 File 对象、Blob 对象或者 MediaSource 对象(媒体资源)。
下载 HTML
在网页打不开右键菜单时可以试试这个方法
参考:下载html
fetch('https://xxx/xxx.htm').then(
response => response.blob()
).then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = '文件名.html';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
}
);
导出txt文件
适用于接口返回文件流的情景
// result.data 为接口返回的二进制文件流
const data = result.data;
const link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
const urlObject = window.URL || window.webkitURL || window;
const exportBlob = new Blob([data]);
link.style.display = 'none'
link.href = urlObject.createObjectURL(exportBlob);
link.download = `导出文件.txt`; //命名下载名称
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
// 下载完成进行释放
urlObject.revokeObjectURL(url);
导出PDF
如果接口返回的文件流,下载方式和上面的类似;
如果是链接,并且网站和文件在同一个域名下,使用a
标签方式下载;
如果下载的PDF文件跨域,又要求下载,最简单的是在HTML中使用a
标签打开新标签页,使用 Edge 或 Chrome 浏览器,利用浏览器解析预览,在预览页是支持下载的。
<a class="u-pdf" href="http://www.doe.zju.edu.cn/_upload/article/files/a0/22/595bdc2b4ca28f90f51ca3b3ffc5/45c3e922-550f-45a2-8602-64b9c202b33e.pdf" target="_blank"></a>
表单下载
适用于链接下载,同样受同源策略影响,不同域名下执行的是预览。
const form = document.createElement("form")
form.method = "get"
form.action = 'http://www.doe.zju.edu.cn/_upload/article/files/a0/22/595bdc2b4ca28f90f51ca3b3ffc5/45c3e922-550f-45a2-8602-64b9c202b33e.pdf' // 链接地址
const input = document.createElement("input")
input.name = "token"
input.type = "hidden"
// input.value = sessionStorage["token"]
form.appendChild(input)
document.body.appendChild(form)
form.submit();
document.body.removeChild(form)