简体   繁体   中英

Create file from FileReader.readAsArrayBuffer()

i am afraid i am either too dumb to use google correctly or having a weird problem nobody not knowing what they're doing ran into.

The goal is to upload a file to a server and then download it again.
However, the server is a custom backend which handles all contents as pure byte array, since it is designed to cope with user input as well as machine-to-machine communication.

I am running a vue.js frontend with node.

I am already able to upload a file as byte array and load that byte array back to the frontend, but now i want to provide the user with the possibility to download that byte array as file .
The user has to enter the file type in the download screen and if they enter the wrong type, the file is corrupt. That would be ok.
Right now, even when i enter the correct file type, the file is corrupted (tested with PDFs and Word files).

Here is my code:
Upload:

<input v-if="type==types.file" id="input-field" ref="file" type="file" @change="handleFileUpload()">

      handleFileUpload(){
        this.value = this.$refs.file.files[0];
      },

      submitFile(){
        var reader = new FileReader();
        var self = this;
        reader.onload = function(event){
          self.value = new Uint8Array(event.target.result);
          self.$notify('succes', 'Dateiupload abgeschlossen');
        };
        reader.onerror = function(event){
          self.$notify('error', 'Fehler beim Dateiupload');
        }
        reader.readAsArrayBuffer(this.value);
      },

Download:

parseFileValueFromByteArray(byteArray){
        const downloadElement = document.createElement('a');
        downloadElement.style.display = 'none';
        downloadElement.href = window.URL.createObjectURL(new File(byteArray, this.name));
        downloadElement.download = this.name;
        document.body.appendChild(downloadElement);
        downloadElement.click();
        window.URL.revokeObjectURL(downloadElement.href);
        return this.value;
}

I get the download-Window to open and download the file, however pdf-Readers (or Word, in that case) show "File corrupted".

What am i doing wrong in creating a valid file? I guess i'm somehow encoding file-metadata (since js File is more than the pure bytes) without decoding the bytes correctly.
So how can i revert FileReader.readAsArrayBuffer() back to a file?

Thanks in advance!

Edit:
Weird thing i noticed: Original pdf file size is 99KB. byteArray length is 100392.
File size from new File(byteArray) gives size of 255KB. Converting byte to text (using new TextEncoder("utf-8).decode(byteArray)) ) gives me something roughly similar to opening a pdf with notepad++, but opening the downloaded file with notepad++ gives me as stream of numbers).
Maybe this help find the error?

So, i've researched more and found this . I have no idea why, but instead of new Blob(byteArray) i have to do new Blob([byteArray]). This gives me the possibility to set.pdf file type in Download and receive a valid file.

To have everything in one place, what i am doing is:
Upload:

<input id="input-field" ref="file" type="file" @change="handleFileUpload()">
<button @click="submitFile()">Start upload</button>

handleFileUpload(){
    this.value = this.$refs.file.files[0];
},

submitFile(){
    var reader = new FileReader();
    var self = this;
    reader.onload = function(event){
        self.value = new Uint8Array(event.target.result);
        self.$notify('succes', 'File uplaoded');
    };
    reader.readAsArrayBuffer(this.value);
}

Download:

//this.payload is set with base64 representation of upload and then load() is called
load(){
    this.base64ToByteArray();
    this.parseFileValueFromByteArray(this.byteArrayPayload);
},

base64ToByteArray(){
    this.rawPayload = this.payload;
    this.byteArrayPayload = Uint8Array.from(atob(this.rawPayload), c => c.charCodeAt(0))
},

parseFileValueFromByteArray(byteArray){
    const downloadElement = document.createElement('a');
    downloadElement.style.display = 'none';
    downloadElement.href = window.URL.createObjectURL(new Blob([byteArray]));
    downloadElement.download = this.name;
    document.body.appendChild(downloadElement);
    downloadElement.click();
    window.URL.revokeObjectURL(downloadElement.href);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM