1

I'm testing this code that I found somewhere on the web. I also tried code that I found in this answer, but nothing seems to be working as I want it to. Here is my javascript:

function fileUpload(url, fileData, fileName) 
{
   var fileSize = fileData.length,
     boundary = "---------------------------7da24f2e50046",
     xhr = new XMLHttpRequest();

   xhr.open("POST", url, true);
          // simulate a file MIME POST request.
   xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
   xhr.setRequestHeader("Content-Length", fileSize);

   var body = "--" + boundary + "\r\n";
   body += "Content-Disposition: form-data; name='file'; filename='" + fileName + "'\r\n";
   body += "Content-Type: application/octet-stream\r\n\r\n";
   body += fileData + "\r\n";
   body += "--" + boundary + "--";
   alert(body);
    xhr.onreadystatechange = function ()
    {
        if (xhr.readyState == 4 && xhr.status == 200)
        {
            alert(xhr.responseText);
        }
    }

   xhr.send(body);
   return true;
}

function send()
{
    fileUpload("receive.php", "abcdefg", "foo.txt");
}

And this is my "receive.php" file:

<html>
<head>
</head>
<body>
<?php
    foreach ($_POST as $var => $value) echo "$var = $value<br>n"; 
?>
</body>
</html>

I'm getting the "receive.php" HTML back but without anything being echoed. But if I actually send a file from an HTML form it echos the file name.

I'm also trying to use Fiddler2 to intercept some real file uploads to see what the POST message is, but I can't seem to find the file content anywhere in the message. I figured the file's content might be encoded somehow so I tried sending a pretty large file, about 2MB, to see if I can find some big chunk of data anywhere in the message being sent, but I didn't. I just see the header and the file name.

Am I missing something?

Edit I really feel I'm missing something obvious. Here is a screenshot of Fiddler2 when I upload a real file:

fiddler screenshot

The content length is the size of the string at the bottom, which doesn't include the file's content but just the file name. The function I'm using and every javascript code that does what I'm trying to do set the content length to a string that includes the file's content and the boundary and other information as you can see in my code above. So my function is creating a POST message that has a different structure that the POST message that Fiddler is showing me.

And where in the world is the file content. Another weird thing is that when I send a 2MB size file from IE, the page navigates to the page that receives the file almost instantaneously, as if nothing is being really sent. I'm very confused.

Edit2 I messed up. There was something wrong with the FORM I was using to test uploads. I'm using another form and now I can see the file contents in Fiddler. I think is probably because I was missing the "enctype='multipart/form-data'" So now I can see why is my javascript not working. I'll let you know when I find a solution.

Community
  • 1
  • 1
Juan
  • 15,274
  • 23
  • 105
  • 187

3 Answers3

1

Javascript cannot read content of files on your hard disk. Given your example, there is no way to populate the fileData variable.

James
  • 20,957
  • 5
  • 26
  • 41
0

This worked:

function SendFile(url, fileName, fileContent) 
{
    xhr = new XMLHttpRequest();

    xhr.open("POST", url, true);
    var boundary = '---------------------------7da24f2e50046';
    xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

    var body = "" +     
        '--' + boundary + '\r\n' + 
        'Content-Disposition: form-data; name="file[]"; filename="' + fileName + '"' + '\r\n' + 
        'Content-Type: text/plain' + '\r\n' + 
        '' + '\r\n' + 
        fileContent + '\r\n' + 
        '--' + boundary + '--' + 
        ''; 

    xhr.onreadystatechange = function ()
    {
        if (xhr.readyState == 4 && xhr.status == 200)
        {
            alert(xhr.responseText);
        }
    }

   xhr.send(body);
   return true;
}
Juan
  • 15,274
  • 23
  • 105
  • 187
-1

You can't send file data with an ajax request. Most every framework out there masks this by creating a hidden iframe and then posting that iframe to your server. To the client, it looks like ajax; however, it's just a workaround to the original problem. You will need to do something similar to get the effect; find the ajax file upload library of your choice and use that, or write your own iframe posting solution.

Tejs
  • 40,736
  • 10
  • 68
  • 86
  • 3
    This is incorrect. You can send file data with AJAX; it just only works in newer browsers. – Stefan Kendall May 17 '11 at 17:20
  • @stefan-kendall Can you please point the resource saying how to do this in modern browsers? There are widely implemented solutions using Flash for it, but I have not seen any JavaScript-only solution. – Tadeck May 17 '11 at 18:39
  • I should be posting it pretty soon ;)... I hope – Juan May 17 '11 at 18:41
  • I would hope not. If you can mimic a file upload with JavaScript, you could upload arbitrary files from the client to the server, without the user intervening? Doesn't that *scream* a huge, gaping security hole? It does to me. – Berry Langerak May 17 '11 at 18:42
  • No, because that doesn't mean I can read his hard drive. I'll craft the file contents in my code. – Juan May 17 '11 at 18:45