2

I'm writing a chrome extension content script which will embed itself on some pages, and when there are certain file type links (.doc, .torrent, etc) it will download that file, and then do a file POST to a python web server which will save that file. The python server is working, and handles a normal multipart/form-data POST request, and successfully saves the file when I use the html interface I wrote for it.

I have javascript downloading the file properly:

var req = new XMLHttpRequest();
req.open('GET', 'http://foo.com/bar.torrent', false);
req.overrideMimeType('text/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
var response = req.responseText;

And then when I try to create a POST request and upload it

// Define a boundary, I stole this from IE but you can use any string AFAIK
var boundary = "---------------------------7da24f2e50046";
var xhr = new XMLHttpRequest();
var body = '--' + boundary + '\r\n'
         // Parameter name is "file" and local filename is "temp.txt"
         + 'Content-Disposition: form-data; name="upfile";'
         + 'filename="temp.torrent"\r\n'
         // Add the file's mime-type
         + 'Content-type: application/bittorrent\r\n\r\n'
         + response + '\r\n';
         //+ boundary + '--';
xhr.open("POST", "http://python.server/", true);
xhr.setRequestHeader(
    "Content-type", "multipart/form-data; boundary="+boundary

);
xhr.onreadystatechange = function ()
{
    if (xhr.readyState == 4 && xhr.status == 200)
        alert("File uploaded!");
}
xhr.send(body);

It thinks that it uploaded successfully, but when I try to open the file it says the data is corrupted. I think this is some kind of encoding issue, but I'm not 100% sure.

Any thoughts would be very helpful.

Nikhil
  • 485
  • 1
  • 4
  • 16

1 Answers1

2

Your upload method does not work, because all binary characters are encoded as UTF-8. I posted the explanation and solution in an answer at this question.

In your case, you don't need to manually create the post data. Request the initial data in a smart way, and use the FormData object to post the binary data. For instance:

var x = new XMLHttpRequest();
x.onload = function() {
    // Create a form
    var fd = new FormData();
    fd.append("upfile", x.response); // x.response is a Blob object

    // Upload to your server
    var y = new XMLHttpRequest();
    y.onload = function() {
        alert('File uploaded!');
    };
    y.open('POST', 'http://python/server/');
    y.send(fd);
};
x.responseType = 'blob';    // <-- This is necessary!
x.open('GET', 'http://foo.com/bar.torrent', true);
x.send();

Note: I replaced false with true at the initial request. Avoid using synchronous XMLHttpRequest when it's also possible to asynchronously create the request.

If you don't understand the answer, here are more examples with thorough explanations:

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678