[TOC] #### 前言 --- JavaScript 点击跳转文件地址时,有的文件会直接下载,而有的文件则在浏览器中直接打开,这主要取决于浏览器对文件类型的处理方式和服务器的响应头设置 浏览器对文件类型的处理 + 需要下载的文件:zip、docx 等文件,通常会触发下载 + 可在浏览器中打开的文件:图片(png、jpg)、视频(mp4)、文本文件(txt)等,浏览器会尝试打开这些文件 跨域和安全策略 + 如果文件来自不同域名,浏览器的安全策略(CORS)可能会影响文件的处理方式 + 某些文件可能因为安全原因被浏览器阻止直接打开,从而触发下载 #### a 标签的 download 属性 --- 通过动态创建一个 a 标签,并设置 href 和 dowload 属性来触发下载 适用于同源或支持 cors 的跨域文件下载,也可以下载一个 base64 格式的文件 ```javascript function download(url, fileName) { const a = document.createElement("a") a.href = url a.download = fileName a.click() } ``` 使用示例:后端接口返回一个 base64 格式的二维码图片,前端按钮需要实现点击按钮将图片下载到本地的功能 ```javascript download('data:image/png;base64,iVBORwxxxxx', 'qrcode.png') ``` #### 将网络地址文件下载到本地 --- 从指定 URL 下载文件并触发并触发浏览器的下载行为,这种实现方式可以绕过浏览器的同源策略限制 + 检测 url 地址,然后获取文件名称 + 使用 XMLHttpRequest 发起文件下载请求 + onreadystatechange 下载状态监控,监听请求状态变化 + onload 处理下载完成后的逻辑,请求成功时创建一个 a 标签触发浏览器的下载行为 ```javascript // 下载文件并导出本地 function downloadFile(url, name = '') { // 检测文件地址 if (url.substr(0, 4) !== 'http') { throw new Error("请传入一个网络地址"); } // 获取文件名称 let fileName; if (name) { const index = url.lastIndexOf('.') fileName = name + (index === -1 ? url : url.substr(index)) } else { const index = url.lastIndexOf('/') fileName = index === -1 ? url : url.substr(index + 1) } // 执行文件下载 const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.responseType = 'blob'; xhr.onload = () => { if (xhr.status === 200) { const url = window.URL.createObjectURL(xhr.response) const a = document.createElement('a'); a.href = url a.download = fileName a.click() } else { console.log('文件下载失败'); } } xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status == 200) { console.log('文件下载成功'); } } else if (xhr.readyState === 3) { console.log('文件下载中'); } } xhr.send(); } ``` 使用示例: ```javascript // 下载文件(导出时默认使用原文件名) downloadFile('https://img.xxx.com/thumb/xxxx.png') // 下载文件,并且指定文件名称(不需要写文件后缀名,会自动拼接) downloadFile('https://img.xxx.com/thumb/xxxx.png', 'qrcode') ```