实现原理:直接用浏览器访问下载链接,唤起浏览器下载功能
window.location.href = '下载链接';
// 或者
window.open('下载链接');
缺点:无法(从前端)自定义下载文件名,下载可预览文件(图片,音乐、视频等)时,会跳转新的界面
实现原理:创建一个a标签,然后点击它,即把下面的标签用js创建出来
<a href="下载链接" download="文件名(如:a.zip)">下载</a>
const a = document.createElement('a')
a.href = '下载链接'
a.download = '文件名'
a.style.display = 'none'
a.target = 'downloadFile'
document.body.appendChild(a) // 兼容火狐
a.click()
document.body.removeChild(a) // 移除a标签
缺点:下载可预览文件时,会跳转新的界面,对于跨域请求download属性会失效,也就是说无法自定义下载文件名
由于上面是方法会打开新的界面,所以我们需要对下载链接进行一些处理,比如转为blob格式:
// 这里需要发送一次请求将下载地址里的文件转为blob格式,进行下载(发送请求时同样会存在跨域问题,如果跨域的话需要在nginx配置代理)
const blob = await fetch('下载链接').then(res => res.blob())
content = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = content
a.download = '文件名'
document.body.appendChild(a) // 兼容火狐
a.click()
document.body.removeChild(a) // 移除a标签
window.URL.revokeObjectURL(content) // 释放content对象
也可以用ajax请求转为blob格式:
const x = new window.XMLHttpRequest()
x.open('GET', '下载链接', true)
x.responseType = 'blob'
x.onload = () => {
const content = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = content
a.download = '文件名'
document.body.appendChild(a) // 兼容火狐
a.click()
document.body.removeChild(a) // 移除a标签
window.URL.revokeObjectURL(content) // 释放content对象
}
x.send()
自然也可以发送axios请求:
axios({
method: 'get',
url: '下载链接'
responseType: 'blob',
}).then((res) => {
if (res && res.status === 200) {
const content = window.URL.createObjectURL(new Blob([response.data]));
const a = document.createElement('a') // 创建a标签
a.href = content
a.download = '文件名'
document.body.appendChild(a) // 兼容火狐
a.click()
document.body.removeChild(a) // 移除a标签
window.URL.revokeObjectURL(content) // 释放content对象
}
}
缺点:需要对下载链接进行请求,将下载的文件转为blob格式,所以自然少不了跨域问题,并且blob格式无法在手机端浏览器下载,所以建议和上面的配合使用,手机端用上面的url方法下载,电脑端用blob
如果是文字的话,则无需再发送请求,可直接将文字转为blob格式
const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
// 只有上面的转为blob格式不同,下面的都是一样的
content = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = content
a.download = '文件名'
document.body.appendChild(a) // 兼容火狐
a.click()
document.body.removeChild(a) // 移除a标签
window.URL.revokeObjectURL(content) // 释放content对象
const url = '下载地址'
const form = document.createElement('form')
form.style.display = 'none'
form.setAttribute('target', '_blank')
form.setAttribute('method', 'get')
form.setAttribute('action', url)
// 创建一个input控件:<input type="hidden" name="请求参数名" value="请求参数值"/>
const input = document.createElement('input')
// 设置input属性
input.setAttribute('type', 'hidden')
input.setAttribute('name', '请求参数名');
input.setAttribute('value', '请求参数值');
form.appendChild(input)
document.body.appendChild(form)
form.submit()
document.body.removeChild(form)
下载可预览文件时,会跳转新的界面
iframe下载不会出现向a标签那样的跳转问题,但是iframe兼容性较差,反正我在测试中没成功过
const url = '下载地址';
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.style.display = 'none';
iframe.onload = function() {
document.body.removeAttribute(iframe);
}
document.body.appendChild(iframe);
const url = '图片下载地址'
const a = document.createElement('a')
a.setAttribute('download', '文件名称')
const image = new Image()
// 添加时间戳,防止浏览器缓存图片
image.src = url + '?timestamp=' + new Date().getTime()
// 设置 crossOrigin 属性,解决图片跨域报错(还需要在后端设置允许跨域请求,否则仍会出现跨域问题)
image.setAttribute('crossOrigin', 'Anonymous')
image.onload = () => {
// 将图片转为base64
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0, image.width, image.height)
// 获取图片后缀名
const extension = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase()
// 部分图片地址可能没有后缀名,默认为png格式
const base64Url = canvas.toDataURL('image/' + extension, 1)
// 也可以直接写死后缀名
// const base64Url = canvas.toDataURL("image/png")
a.href = base64Url
a.click()
}
缺点:同样需要处理跨域问题
使用FileSaver下载文件时仍然存在跨域问题
下载:
npm install file-saver --save
# 或者:
bower install file-saver
引入:
import fileSaver from 'file-saver'
var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
fileSaver.saveAs(blob, "hello world.txt");
var canvas = document.getElementById("canvasid");
canvas.toBlob(function(blob) {
fileSaver.saveAs(blob, "image.png");
});
fileSaver.saveAs('地址', '名称')
var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"});
fileSaver.saveAs(file);
fileSaver.saveAs(blob, '文件名')
转为blob格式的方法,上面已经写了很多个了,这里取其中一个做示范:
const blob = await fetch('下载链接').then(res => res.blob())
fileSaver.saveAs(blob, '文件名')