This is the third day of my participation in Gwen Challenge.

File download requirements

A preliminary study

The business requirements require that files can be downloaded by clicking.

Then I thought, isn’t a link with a new download attribute?

Set the url of link A to the address of the image to download, and set the download property to the file name to download.

<a href="https:wwww.a.com/a/b" download="Some specified value">
Copy the code

Tried and found it didn’t work. It turns out that the domain name of the image address is inconsistent with the domain name of the current page. The documentation states that only same-origin urls are supported.

In other words, this method only supports same-origin urls and only ignores file name downloads.

Supports custom file names

How do you support custom file names? The document contains this sentence:

Although the HTTP URL needs to be in the same source, you can use blob: URL and data: URL to make it easy for users to download content generated using JavaScript (for example, photos created using an online drawing Web application).

So how do we get the blob: URL of a file?

Url.createobjecturl () is required. Url.createobjecturl () takes “File object, Blob object, or MediaSource object created for the URL.”

To get the Blob object of the file, use XMLHttpRequest’s responseType as’ Blob ‘.

function getBlob(url) {
  return new Promise(resolve= > {
    const xhr = new XMLHttpRequest()

    xhr.open('GET', url, true)
    xhr.responseType = 'blob'
    xhr.onload = () = > {
      if (xhr.status === 200) {
        resolve(xhr.response)
      }
    }

    xhr.send()
  })
}

function saveAs(blob, filename) {
  const link = document.createElement('a')

  link.href = window.URL.createObjectURL(blob)
  link.download = filename

  // fix Firefox
  link.style.display = 'none'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)

  window.URL.revokeObjectURL(link.href)
}

async function downloadImage (url,filename){
  const blobUrl = await getBlob(finalUrl)
  saveAs(blobUrl, img.downloadName)
}

downloadImage('https:wwww.a.com/a/b'.'Some specified value')
Copy the code

So you can download any file, success!

Other download methods

Is there another way to download material?

For pictures and videos, you can also use Canvas for download

export function downloadImg(img) {
  return new Promise<void> (reslove= > {
    const imgDom = new Image()
    imgDom.setAttribute('crossOrigin'.'Anonymous')
    imgDom.src = img.url

    imgDom.addEventListener('load'.() = > {
      const alink = document.createElement('a')
      const canvas = document.createElement('canvas')
      const context = canvas.getContext('2d')
      if(! context)return

      canvas.width = img.width
      canvas.height = img.height
      context.drawImage(imgDom, 0.0)

      alink.download = img.downloadName
      alink.style.display = 'none'
      alink.href = canvas.toDataURL('image/jpeg')
      alink.click()
      reslove()
    })
  })
}
Copy the code

Also used the download attribute of a link, the disadvantage is that the image will be larger than the actual size. I stepped into this hole during the project. When drawing an image to a canvas, the image is exported with base64 encoding, which results in a volume change of about 33%.

HTTP Request download

Content-Disposition: attachment; filename=”filename.jpg”

Files placed on cloud services can be downloaded and renamed directly from the cloud in this way.

The resources

  1. www.jianshu.com/p/654501501…
  2. Developer.mozilla.org/zh-CN/docs/…
  3. Stackoverflow.com/questions/4…
  4. Cloud.tencent.com/document/pr…