8

I'm trying to upload a static file from within my JS code. I have a .tgz file that I want to send as POST parameter. I've dumped my file to a hex string fileDatalike: var file = "\xff\x01\x08 .....

I want to send as the body content of a multi form post data. It seems like when I try to just .send(file) the hex values become mangled and the file is corrupted.

JS looks something like this:

var url = "/index/upload/"

var fileData = '\xF1\x08\x00\x00........\x00\x00';
//whole file binary content in hex) 

boundary = "----------3333338220322",
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
var body = "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="newFile"; filename="filename.tgz"\r\n';
body += "Content-Type: application/x-gzip\r\n\r\n";
body += fileData + "\r\n";
body += "--" + boundary + "--";
xhr.send(body);

Not sure what goes wrong. The request seems to look exactly like if I manually upload the file, but the binary data seems different when observing through a proxy. Is there a better way to send files if i need to have its whole content in the JS code itself?

  • How the data is changing in the upload url ? Can you test that ? – xTrimy Apr 18 '19 at 16:00
  • Here is the beginning of what i set in javascript and what it became in the post request: var original = '\x1f\x8b\x09\x00\x77\xa0\xb8\x5c\x00\x03' ; became in the post request = fd 08 00 77 fd fd 5c 00 03 fd – Junior Almeida Apr 18 '19 at 18:00
  • Try sending some random data without "\" and tell me what is the result – xTrimy Apr 18 '19 at 18:28
  • Why do you send it has an Hex string exactly? Just send the file. Now, xhr.send accepts either a FormData, a Blob/File or an ArrayBuffer, but not strings. If you wish to send an utf8 string, use a FormData or create a text file from this string (`new Blob([yourdata])`), but once again that sounds like a pretty terrible idea... – Kaiido Apr 18 '19 at 19:13

1 Answers1

4

Figured out a wait to make it work. Using base64 to encode the file instead of hex.

var b64data = 'H4sIAHegu.....';
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
  const byteCharacters = atob(b64Data);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, {type: contentType});
  return blob;
}

const contentType = 'application/x-gzip';
const blob = b64toBlob(b64data, contentType);

Then used this blob as the file content.

Solution found from here:

Convert base64 png data to javascript file objects

offsec/awae ;)