下载图片主要利用a标签的download属性,但如果图片跨域,点击a标签时,不会下载href指定的图片,而是跳转到href指定的网页,因此需要先本地化图片,才能下载图片

第一步,图片本地化

以下两种方法都需要图片允许跨域。需要服务器配置跨域的响应头。若是其他服务器,可以考虑让后端人员进行一次转发。或者前端设置跨域代理。

方法一:手动发起请求,获取图片的blob

  • 将responseType设置为blob,请求图片,获取图片的blob对象
  • 利用URL.createObejectURL方法,为blob图片创建链接

    1. function getLocalUrl(url) {
    2. // 因为发送请求是异步执行的,所以使用promise包裹
    3. return new Promise((resolve, reject) => {
    4. let xhr = new XMLHttpRequest()
    5. // 要求响应格式的是blob
    6. xhr.responseType = 'blob'
    7. xhr.open('get', url, true)
    8. xhr.onreadystatechange = function () {
    9. if (xhr.readyState === 4) {
    10. // 请求成功,URL.createObjectURL将blob对象转换为本地url
    11. resolve(URL.createObjectURL(xhr.response))
    12. }
    13. }
    14. xhr.send()
    15. })
    16. }

    方法二:利用canvas将图片转换为base64格式

  • 先将图片插入到canvas

  • 利用canvas的toDataURL方法,将图片转为base64

    1. function getLocalUrl(url) {
    2. // 图片加载非同步,需要promise包裹
    3. return new Promise((resolve, reject) => {
    4. // 创建图片,并将图片属性设置为可跨域
    5. const img = document.createElement('img')
    6. // 不设置该属性canvas无法将图片转为base64
    7. img.setAttribute('crossorigin', 'anonymous')
    8. img.src = url
    9. img.onload = function () {
    10. const canvas = document.createElement('canvas')
    11. canvas.width = img.width
    12. canvas.height = img.height
    13. const ctr = canvas.getContext('2d')
    14. // 画图
    15. ctr.drawImage(img, 0, 0, img.width, img.height)
    16. resolve(canvas.toDataURL())
    17. }
    18. })
    19. }

    第二步,使用a标签的download属性下载图片

  • 给a标签设置download属性,属性值是图片的名称

    1. <a href="" download="yy.jpg" id="down">下载图片</a>
    2. <script>
    3. const a = document.getElementById('down')
    4. getLocalUrl(url).then(res => {
    5. a.href = res
    6. })
    7. </script>