Javascript: Uploading a file... without a file Javascript: Uploading a file... without a file javascript javascript

Javascript: Uploading a file... without a file


If you don't need support for older browsers you can use the FormData Object, which is part of the File API:

var formData = new FormData();var blob = new Blob(['Lorem ipsum'], { type: 'plain/text' });formData.append('file', blob,'readme.txt');var request = new XMLHttpRequest();request.open('POST', 'http://example.org/upload');request.send(formData);

File Api is supported by all current browsers (IE10+)


Why not just use XMLHttpRequest() with POST?

function beginQuoteFileUnquoteUpload(data){    var xhr = new XMLHttpRequest();    xhr.open("POST", "http://www.mysite.com/myuploadhandler.php", true);    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");    xhr.onreadystatechange = function ()    {        if (xhr.readyState == 4 && xhr.status == 200)            alert("File uploaded!");    }    xhr.send("filedata="+encodeURIComponent(data));}

The handler script at the server just writes the file data to a file.

EDIT
File upload is still a http post with a different content type. You can use this content type and separate your content with boundaries:

function beginQuoteFileUnquoteUpload(data){    // 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="file";'             + 'filename="temp.txt"\r\n'             // Add the file's mime-type             + 'Content-type: plain/text\r\n\r\n'             + data + '\r\n'             + boundary + '--';    xhr.open("POST", "http://www.mysite.com/myuploadhandler.php", 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);}

If you want to send additional data, you just separate each section with a boundary and describe the content-disposition and content-type headers for each section. Each header is separated by a newline and the body is separated from the headers by an additional newline. Naturally, uploading binary data in this fashion would be slightly more difficult :-)

Further edit: forgot to mention, make sure whatever boundary string isn't in the text "file" that you're sending, otherwise it will be treated as a boundary.


Just sharing the final result, which works - and has clean way of adding/removing parameters without hardcoding anything.

var boundary = '-----------------------------' +            Math.floor(Math.random() * Math.pow(10, 8));    /* Parameters go here */var params = {    file: {        type: 'text/plain',        filename: Path.utils.basename(currentTab.id),        content: GET_CONTENT() /* File content goes here */    },    action: 'upload',    overwrite: 'true',    destination: '/'};var content = [];for(var i in params) {    content.push('--' + boundary);    var mimeHeader = 'Content-Disposition: form-data; name="'+i+'"; ';    if(params[i].filename)        mimeHeader += 'filename="'+ params[i].filename +'";';    content.push(mimeHeader);    if(params[i].type)        content.push('Content-Type: ' + params[i].type);    content.push('');    content.push(params[i].content || params[i]);};    /* Use your favorite toolkit here */    /* it should still work if you can control headers and POST raw data */Ext.Ajax.request({    method: 'POST',    url: 'www.example.com/upload.php',    jsonData: content.join('\r\n'),    headers: {        'Content-Type': 'multipart/form-data; boundary=' + boundary,        'Content-Length': content.length    }});

This was tested to work on all modern browsers, including but not limited to:

  • IE6+
  • FF 1.5+
  • Opera 9+
  • Chrome 1.0+
  • Safari 3.0+