Using ajax to do a file submit

I have read many online articles on this topic. However, they either just show how to do ajax form submission, or how to submit just files. In my case, well I bet in most real life situations, we need to submit both ordinary text/selection/radio values and files.

Here is how to do it.

HTML forms. Yea, whatever. Just set something up.




Submit 

Notice I didn’t use the form tag. My philosophy here is that: since we will decide the data set during the ajax submission, there is really no need to declare a form here.

Then here comes the ajax part.

$('document').ready(function(){
	// bind actions to the submit button
	$('#submit_btn').click(function(){
		submit_xhr();
	});
});

// submission
function submit_xhr(){
 
	// our file obj
	file_obj = document.getElementById('file1').files[0];

	// using FormData, makes your life much easier
	var formData = new FormData();
	// append key-value pairs
	formData.append('text1', $('#text1').val());
	formData.append('text2', $('#text2').val());
 
	var xhr = new XMLHttpRequest();
	url = "http://somewhere.com/some_dir/upload.php";
	type = "POST";
	xhr.open(type, url, true);
	xhr.onload = function(e) {
		if (xhr.status == 200) {
			if (xhr.statusText != "OK"){
				// something wrong at the server side, not fatal
				alert(xhr.statusText);
				return;
			}
			// success
			alert('could do a window.location.replace(url) here');
		} else {
			// error, something bad happened...
			alert("ErrornStatus: "+xhr.status+"nStatus text: "+xhr.statusText);
		}
	};
 
	xhr.send(formData);
}

I found FormData very easy and intuitive to use. I recommend using that rather than creating a json array when file sending is involved.

So now, we need to receive the content at the server side.

$text1 = $_POST["text1"];
$text2 = $_POST["text2"];

$file_obj = $_FILES["file1"];
$file_name = $file_obj["name"];
$file_type = $file_obj["type"];
$file_size = $file_obj["size"];
$file_tmp_name = $file_obj["tmp_name"];
$file_error = $file_obj["error"];

// do whatever

The $file_error value should be 0 upon a successful transfer. The $file_tmp_name is a local temp file name containing your file content. Everything feels natural now from this point on. You can also double check the $file_size.

If you are a javascript purist, you may want to try out FileReader. Below is some snippet to get you started.

function read_file_content_and_submit(){

	var file_type;
	var file_name;

	var reader = new FileReader();
	reader.onerror = errorHandler;
	reader.onload = function(e){
		data = {
			type: file_type,
			name: file_name,
			content: reader.result
		}
		//alert(data);
		combine_with_others_then_submit(data);
	}

	file_obj = document.getElementById('file1').files[0];
	file_type = file_obj.type;
	file_name = file_obj.name;
	reader.readAsBinaryString( file_obj );
}

Hope this helps!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s