vueuse icon indicating copy to clipboard operation
vueuse copied to clipboard

File download functionality

Open arthabus opened this issue 1 year ago • 2 comments

Clear and concise description of the problem

Scenario:

  1. User clicks a button to download a file from server
  2. this initiates api request to the server that returns file content
  3. now we need to let browser download that file to the user's computer

The last step usually requires to create a fake <a/> tag with the file content in href and then clicking it, then removing. Something like below:

const download = (data, name, type) => {
  const url = window.URL.createObjectURL(new Blob([data], { type }));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', name);
  document.body.appendChild(link);
  link.click();
  setTimeout(() => {
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);
  }, 200);
};

Suggested solution

In module Browser we could provide a method like useDownloadFileFromContent that would do something like below (by no means this is a production ready code but just a reference to show the idea):

const download = (data, name, type) => {
  const url = window.URL.createObjectURL(new Blob([data], { type }));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', name);
  document.body.appendChild(link);
  link.click();
  setTimeout(() => {
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);
  }, 200);
};

Alternative

Manually do all the steps described above

Additional context

No response

Validations

arthabus avatar Jun 09 '24 10:06 arthabus

Using JavaScript to trigger downloads can indeed be a bit more involved than using simple anchor tags, especially considering scenarios where permission checks or additional tasks are required. In the context of the example provided, it might seem more intuitive to utilize anchor tags directly.

In Vue applications, handling downloads can often be streamlined by incorporating authentication checks and enabling download functionality dynamically. This aligns well with Vue's reactive nature.

While the example showcases plain JavaScript, integrating similar functionality into a Vue application is indeed feasible and straightforward. Therefore, it's reasonable to ponder whether such a specific approach, lacking in versatility, would be included in VueUse.

As for using window.open(), it could serve as a viable workaround to achieve similar functionality by opening the file URL in a new tab for download. It's worth considering such alternatives for achieving the desired outcome.

Gianthard-cyh avatar Jun 09 '24 13:06 Gianthard-cyh

There are other scenarios too actually, like when the file that needs to be downloaded is created on client side.
I.e. user clicks a button -> file is generated on client -> then downloaded locally.

For example a snapshot when jpeg is created programmatically or when generating a pdf or relatively small csv file to download etc. etc.

There might be other scenarios too, those are just the ones I've faced and saw people are dealing with.

Of course one can argue about simplicity and versatility, but that's guys for you to decide.

arthabus avatar Jun 10 '24 21:06 arthabus