几种常用的图片下载及会遇到的问题
1、同源路径
直接用a标签+download 属性:
<a href="https://baidu.com" download="百度.jpg">下载</a>
或者用blob文件流的形式:
// 获取图片文件流
download (row) {
const imgUrl = row.fileUrl
let xhr = new XMLHttpRequest()
xhr.open('get', imgUrl, true)
// 至关重要
xhr.responseType = 'blob'
xhr.onload = function () {
if (this.status === 200) {
// 得到一个blob对象
let blob = this.response
// 至关重要
downloadFile(row.fileName, blob) // 下载
}
}
xhr.send()
}
// 下载
downloadFile (fileName, blob) {
var dowloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob)
let evt = document.createEvent('HTMLEvents')
dowloadElement.href = href
dowloadElement.download = fileName
document.body.appendChild(dowloadElement)
evt.initEvent('click', true, true)
dowloadElement.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }))
document.body.removeChild(dowloadElement)
window.URL.revokeObjectURL(href)
},
2、不同源 的路径,这个时候就会报跨域问题(No ‘Access-Control-Allow-Origin’ header is present on the requested resource。),这是因为浏览器同源策略的原因
这个时候有几种方法
1、设置 ‘crossOrigin’, ‘anonymous’
downloadUrl (fileUrl, callback) {
let image = new Image()
// 关键
image.setAttribute('crossOrigin', 'anonymous')
image.src = fileUrl
image.onload = () => {
let canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
let ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0, image.width, image.height)
let ext = image.src.substring(image.src.lastIndexOf('.')+1).toLowerCase()
let dataURL = canvas.toDataURL(ext)
callback(dataURL )
}
}
download (fileUrl, name = 'pic') {
downloadUrl(fileUrl, (imageSrc)=>{
const eleLink = document.createElement('a')
eleLink.download = name
eleLink.href = imageSrc
eleLink.click()
eleLink.remove()
})
}
2、或者跨越的图片让通过nodejs中转一下,或者找后端处理一下, 通过服务器的方式来绕过跨域的问题
3、最近遇到一个ali-oss储存图片的下载问题,也记录下,图片无法下载,报403 禁止访问的问题,通过查看 阿里云 OSS 下载文件,通过文件 URL 下载文件,浏览器中使用 signatureUrl 方法生成用于下载的文件 URL,URL的有效期默认为半小时,即 1800s。
import OSS from 'ali-oss'
import {getOss} from '@/api.js' // 接口获取密匙
// 配置下载功能
async downloadUrl (obj, callback) {
const { result } = await getOss() // 接口获取密匙
let { accessKeyID, accessKeySecret, securityToken } = result // 处理参数
cosnt client = new OSS({
accessKeyId: accessKeyID,
accessKeySecret,
stsToken: securityToken,
endpoint: '', // 你的endpoint
bucket: '' // 你的bucket
})
const filename = obj.name // filename为自定义下载后的文件名。
const response = {
'content-disposition': `attachment; filename=${encodeURIComponent(filename)}`
}
// object-key表示从OSS下载文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
cosnt signatureUrl = client.signatureUrl(obj.url, { response });
callback(signatureUrl)
}
// 下载
downloadUrl({url, name}, (imageSrc)=>{
if(imageSrc){
const eleLink = document.createElement('a')
eleLink.download = name
eleLink.href = imageSrc
eleLink.click()
eleLink.remove()
}
})