Vue/HTML/JS how to download a file to browser using the download tag

Ricky-U picture Ricky-U · Dec 14, 2018 · Viewed 52.4k times · Source

This question is different from the other answer provided, because my question is focused on VUE and if VUE also has a way to prevent the default method.

This question is more specific to HTML 5 "download" along with VUE binding of the :href and why it doesn't work to prevent the default browser behavior of opening the file in a new tab.

Expected behavior : Download the file to the browser

Actual behavior : Opens the file in a new tab

Exception: Only images, pdf and browser compatible files are opened in a new tab, other files like .exe are downloaded as normal - Why is this, can this behavior be changed in html?

Adding target="_blank" does not solve the problem

<a :href="downloadById(item.url)" download>Download</a>

When the above link is clicked, the file is opened in a new browser tab, i need to prevent this default behavior and force a download upon click. The HTML 5 tag "download" is suppose to solve this problem doesn't seem to work.

Chrome has recently deprecated the download tag form working with cross domain downloads. Does vue have a modifier to prevent this default? Are there any other ways to download the file either in javascript or in html?

One proposed solution is to read the URL as a arrayBuffer and then create a new blob in the DOM, and then create an anchor element and click it.. But that seems hacky to force a download of a file.

I am sure their must be a cleaner solution to download a file form a URL, its a trivial problem, hoping for a simple solution.

Thanks.

Answer

Lars Beck picture Lars Beck · Dec 14, 2018

You can fetch the file as a blob and provide it the same way, there will be no request that leads into CORS issues.

Template

<a
  :href="item.url"
  v-text="item.label"
  @click.prevent="downloadItem(item)" />

Vue

methods: {
  downloadItem ({ url, label }) {
    Axios.get(url, { responseType: 'blob' })
      .then(response => {
        const blob = new Blob([response.data], { type: 'application/pdf' })
        const link = document.createElement('a')
        link.href = URL.createObjectURL(blob)
        link.download = label
        link.click()
        URL.revokeObjectURL(link.href)
      }).catch(console.error)
  }
}

Notes: I used Axios for my example but that's not a requirement, the blob's mime type is hardwired for the sake of simplicity.