kennethjiang / js-file-download

MIT License
918 stars 119 forks source link

Downloading everything else than TXT leads to broken file (no server involved) #62

Closed zzynx closed 4 years ago

zzynx commented 4 years ago

Hi, My use case: in my React PWA a user can choose an attachment (of type TXT, JPG, PNG, PDF or ZIP). The user should be able to download that attachment again too. When I chose a TXT file, the downloaded file is correct. Every other type is broken (badly encoded?).

Here's my typescript code (for a ZIP file) stripped down to the bare minimum: It starts with a simple input on my page:

<input  type="file"
             accept=".png,.jpg,.jpeg,.pdf,.txt,.zip"
             onChange={this.onFileSelected}/>

and this is the method that is called when a file is chosen:

    onFileSelected = (file) => {
        if (!file) { return; }
        const reader = new FileReader();
        reader.onloadend = () => {
             const fileData = reader.result as string;
             const ZIP_HEADER = 'data:application/x-zip-compressed;base64,';
             const dataIndex = fileData.indexOf(ZIP_HEADER);
             const binaryData = (dataIndex >= 0) ? fileData.substr(ZIP_HEADER.length + dataIndex) : fileData;

             // having that base64 encoded file content (without the header), now decode it
             // and feed it to fileDownload to save it as a zip file with the original name
             const fileDownload = require('js-file-download');
             fileDownload(atob(binaryData), file.name, 'application/x-zip-compressed');
        };
        reader.readAsDataURL(file);
   };

Result: while my initial Hello.zip file (a zip containing a text file 'hello.txt' containing just the word 'Hello') is 123 bytes, the resulting downloaded file is 137 bytes and it can't be opened.

Screenshot of both zip files opened with Notepad++: https://i.postimg.cc/2Shxpbvx/Screenshot-122.png The upper one is the original, good one. The lower one is the downloaded one. As you can see, there's something wrong with the two "XV,P," parts in the file. Similar problems with PDF, PNG and JPG files. It works only correctly for TXT files (using TXT_HEADER = 'data:text/plain;base64,'; and as mimetype 'text/plain' then of course)

What is going wrong? Do I do something wrong? Or is js-file-download messing up? Any help much appreciated.

penkov1234 commented 4 years ago

I'm also getting corrupted .xls file. Tested on Postman and it works correctly.

ignatvilesov commented 4 years ago

Binary files should be in Blob format :rocket:

Related issue #54

kindrowboat commented 4 years ago

Thank you @ignatvilesov for pointing folks in the right direction.