Hello! The task is to upload the file (.exe) to the server, the selected file via

<input type="file" id="myfile"> 

I read like this (javascript):

 var myfile=''; var input = document.getElementById('myfile'); input.onchange = function(evt){ var tgt = evt.target || window.event.srcElement, files = tgt.files; if (FileReader && files && files.length) { var fr = new FileReader(); fr.onload = function(){ myfile = fr.result; } fr.readAsDataURL(files[0]); } } 

Now I have a variable "myfile" of the form:

 "data:application/msdownload;base64,0J/RgNC40LLQtdGCINC80LjRgCE= .... и т.д." 

Those. In base64 data there is a raw file ... When I try to upload a file to the server, everything is fine, BUT the encoding changes ... What am I doing wrong?

Uploading:

  var fd = new FormData(); var b = new Blob([atob(decodeURIComponent((myfile).split(',')[1]))],{type: 'application/msdownload'}); fd.append('file', b, "myfile.exe"); var xhr = new XMLHttpRequest(); xhr.open("POST", "http://myserver/"); xhr.send(fd); 

Everything is good. The file is loading norms. But the downloaded file has a different encoding ... Ie it does not open. Because of this, the file size changes.

I tried to add a header of different encodings when sending, but to no avail.

 xhr.setRequestHeader("Content-Type", "charset=windows-1251"); ............. xhr.setRequestHeader("Content-Type", "charset=utf-8"); и др...... 

What's wrong?

Please do not offer to download the file directly ... the file must be saved locally for a while ... and then unloaded.

Updated (to clarify the issue):

We have a Base64 line of the form:

 0J/RgNC40LLQtdGCINC80LjRgCE= 

We know that it contains the contents of the executable file "SecretFile.exe". Obtained by the method described above.

When decoding with standard window.atob, the content is not equal to the source. How to get the source code from raw encoded in Base64, FileReader.

RESOLVED:

Attempts to transcode from encoding to encoding (as suggested by @Other UTF-8, 1251 ..., etc.) did not give any result. As well as attempts to read a file with different readAsText () methods, readAsBinaryString () ... however, the moment with Base64 was important, namely readAsDataURL (), which contains the same data as when reading by other methods, in a convenient form for storing them.

The solution, as often happens, is simple. Thank you @GoncharovAleksandr for answering my question on a big SO

As it turned out, the decoded string from Base64 is not directly the "image" of the file, but the characters for each byte of binary data that can be converted using the ( source ) function:

 function b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; } 

Thanks to all! Maybe someone will come in handy.

  • This question is a duplicate of this.stackoverflow.com/questions/568543 . Learning to use the search - Goncharov Alexander
  • Not quite a duplicate, see carefully. - user207618
  • @Other exactly, ATP - Goncharov Alexander
  • @Tommi better edit the question - it’s not at all clear what you need to add to the FormData file from a text variable previously taken from input = file - Goncharov Alexander
  • And why is the intermediate representation of the data-URL and base64, and not stupidly binary ArrayBuffer? - D-side

1 answer 1

You are strangely capturing a file, offering two more simple options:

1.FormData to design with the form of this file

 var fd = new FormData($('#myfile').parents('form:first')[0]); //но название на стороне сервера будет как name у input-а #myfile 

2. Add a file to FormData

 var fd = new FormData(); fd.append('file', $('#myfile')[0].files[0], "myfile.exe"); 

Everything can be sent to xhr. On the server side, work the same way as with a file sent in the usual way.

UPD:
If the task is to load the file with the string previously saved from input = file: try instead of readAsDataURL - readAsText . As says MDN - there you can substitute a specific encoding. And already with this text create Blob. Hope to help, but not sure.

UPD2:
And now - almost the answer to your question on a large SO . You just need to create a Blob from base64 correctly.

  • You miss that only the data:application/msdownload;base64,0J/RgNC40LLQtdGCINC80LjRgCE= .... и т.д. string can be available data:application/msdownload;base64,0J/RgNC40LLQtdGCINC80LjRgCE= .... и т.д. . - user207618
  • @Other yes, but at the beginning of the question it is clear that this line is read there using input.onchange - Goncharov Alexander
  • "file must be saved locally for a while ". Maybe in localStorage saves, and after N reboots, the browser tries to send. - user207618
  • @GoncharovAleksandr Really initially the base64 string was read using input file. But read the whole question - please, do not offer to download the file directly. - undеfinеd
  • @Other can then add. - Goncharov Alexander