I've gotten this question about 200 times, as have other bloggers, so I thought I'd write up a quick blog post to discuss it.
The short answer is no. Ajax, specifically the feature used to make HTTP requests, cannot do file uploads. Period. This is a security feature enforced at the browser level.
However there are workarounds. The typical workaround uses JavaScript to create a hidden iframe. A new form is created here and then that form is posted to the server. You can then monitor the result of the form post and handle it.
If you Google, you will find about 2 million examples of this. I spent five minutes and picked an example that was simple and direct. This is - most probably - not the best example - but it worked. For this example I'll be using the code from:
Yes, that's a PHP site. Get over it. ;) The example makes use of jQuery and runs as a jQuery plugin.
I downloaded the AjaxFileUpload zip. It provided everything. I copied the JS, CSS files, and images over, and then modified his main demo file to come up with the following base code:
<html>
<head>
<title>Ajax File Uploader Plugin For Jquery</title>
<script src="jquery.js"></script>
<script src="ajaxfileupload.js"></script>
<link href="ajaxfileupload.css" type="text/css" rel="stylesheet">
<script type="text/javascript">
function ajaxFileUpload()
{
$("#loading")
.ajaxStart(function(){
$(this).show();
})
.ajaxComplete(function(){
$(this).hide();
});
$.ajaxFileUpload
(
{
url:'/testingzone/ajaxupload/doajaxfileupload.cfm',
secureuri:false,
fileElementId:'fileToUpload',
dataType: 'json',
success: function (data, status)
{
if(typeof(data.error) != 'undefined')
{
if(data.error != '')
{
alert(data.error);
}else
{
alert(data.msg);
}
}
},
error: function (data, status, e)
{
alert(e);
}
}
)
return false;
}
</script>
</head>
<body>
<div id="wrapper">
<div id="content">
<h1>Ajax File Upload Demo</h1>
<p>Jquery File Upload Plugin - upload your files with only one input field</p>
<img id="loading" src="loading.gif" style="display:none;">
<form name="form" action="" method="POST" enctype="multipart/form-data">
<table cellpadding="0" cellspacing="0" class="tableForm">
<thead>
<tr>
<th>Please select a file and click Upload button</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id="fileToUpload" type="file" size="45" name="fileToUpload" class="input"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td><button class="button" id="buttonUpload" onclick="return ajaxFileUpload();">Upload</button></td>
</tr>
</tfoot>
</table>
</form>
</div>
</body>
</html>
You want to pay particular attention to the ajaxFileUpload function. The only thing I modified was the URL value. To handle the file upload on the server, you handle it like any other file upload. However, his code wanted a JSON structure back. Luckily that is incredibly easy in ColdFusion.
<cfset r = structNew()>
<cfset r["msg"] = "">
<cfset r["error"] = "">
<cfif structKeyExists(form, "fileToUpload") and len(form.filetoupload)>
<cffile action="upload" filefield="fileToUpload" destination="#expandPath("./")#" nameconflict="makeunique">
<cfset r["msg"] = "Your file was #file.clientfile# and had a size of #file.filesize#.">
<cfelse>
<cfset r["error"] = "No file was uploaded.">
</cfif>
<cfoutput>#serializeJSON(r)#</cfoutput>
So obviously if you use some other method, your code will vary, but hopefully this simple example will be enough to get people started.
If readers would like to recommend their own scripts, please do so.