eligrey / FileSaver.js

An HTML5 saveAs() FileSaver implementation
https://eligrey.com/blog/saving-generated-files-on-the-client-side/
Other
21.39k stars 4.38k forks source link

.txt extension added on downloaded files on iphone #785

Open collax opened 1 year ago

collax commented 1 year ago

Hi,

I have a problem that happen only on Iphone, the .txt extension is added at the end of the file when downloaded. It seem to work fine on other devices (even on safari on mac)

Simple sample code that I use:

    var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
    FileSaver.saveAs(blob, this.workout.name+'.zwo');

For example on Iphone, this will give the file a "workout.zwo.txt" name instead of a "workout.zwo"

Is there a way to fix this ?

Thanks

jimmywarting commented 1 year ago

hmm, maybe change the type to something like {type: 'application/octet-stream'}?

snoolord commented 1 year ago

@collax I'm having this exact issue. Have you found a fix?

snoolord commented 1 year ago

if anyone is reading this, i figured out a workaround to download the PDF file without the .txt extension from a Blob. (only checked that this works for PDF specifically) Very hacky, but you need to create a new Blob and specify the type of the Blob to the mimeType: "application/pdf". Maybe there's an enum somewhere that maps file extensions to mimeType and this can be done better, but for now this fixed the issue for me. On desktop, the file downloads like normal and on iPhone it will open the file in the browser and the user can save to their iPhone or iPad.

export const saveFile = async (blob: Blob, suggestedName: string) => {
  const isPdf = suggestedName.includes("pdf");
  if (!isPdf) {
    FileSaver.saveAs(blob, suggestedName);
    return;
  }
  const pdfBlob = new Blob([blob], { type: "application/pdf" });

  const blobUrl = window.URL.createObjectURL(pdfBlob);
  const link = document.createElement("a");
  link.href = blobUrl;
  link.setAttribute("download", `${suggestedName}`);
  document.body.appendChild(link);
  link.click();
  link.parentNode?.removeChild(link);
  window.URL.revokeObjectURL(blobUrl);
};