Page 1 of 1
File uploads on an ajax driven form
Posted: Tue Aug 05, 2008 4:26 pm
by kendall
Hi,
I have an application that I want to develop where I need to submit a form with text and file inputs( if necessary). My delimma is I am using Adobe's SPRY framework which can't submit multi part data forms using ajax. It means that I need to upload the file FIRST (probably through another form maybe?) then submit the form. Apart from this...when a record is made the file needs to have the autoincremented id appended to it so i need to some how reference the uploaded file to be renamed when submitting the text data. Another situation i need to consider is when "cancelling" the form after the fact that the file has been uploading in case the person uses the back button.
I have been wondering how I should design the process flow for this and wanted to get some opinions on what is "feasable" as this method maybe something that I can reuse for other development work.
What is your take on it? what are some "good" approaches?
Re: File uploads on an ajax driven form
Posted: Wed Aug 13, 2008 4:26 pm
by ell0bo
You basically can't submit files using Ajax proper. If there is a way to serialize the data and then send it on I haven't ever come across it. The answer to uploading a file in an Ajax like manor is to utilize an iframe and another Ajax techniques to make it look like you're actually uploading the file.
You first need to set up the form to post the data to an invisible iframe somewhere on the page. This way when you submit the form you don't end up submitting the actual page, hence defeating the purpose of using Ajax. Next you will need to set up a monitoring script to see when the file is done processing.
This means you will need to have two files on the server to aid in this technique, one to upload the file and the other to process the polling data. What happens is are you are uploading the file to the iframe, you poll using ajax to check for the status of the uploaded file. Problem becomes that PHP only runs once the entire file has been submitted to the server, thus the handling script will run only once the entire file has been pushed, where as the polling script can run right from the begining.
All you need to do is set up the Polling script to check if the file is on the server, and return true, otherwise false (i used json for this). If you want, you can check a status file on the server which your upload script will output at the end of the upload process to leave info that you might need, for instance if something is wrong with the file. Your polling script will then have to be able to post these messages back to the user so they know if they file got uploaded successfully or not. Also, you're going to have to watch if for some reason the file gets lost on the way to the server, go giving your polling script a time out will work best.
Now, you can do real time file upload statuses if you use Perl, but that's a little further then I feel like getting into. If you want multiple file getting uploaded, such as an entire directory, then you can use a java applet (or I suppose flash).
Hope that helps (or even makes sense)!
Re: File uploads on an ajax driven form
Posted: Wed Aug 13, 2008 7:28 pm
by kendall
thanks ellobo....
Re: File uploads on an ajax driven form
Posted: Thu Aug 14, 2008 4:43 pm
by blueyon
there is a few I have come accross.
Try jquery form library it has one.
If not then try using an invisable iframe.
Re: File uploads on an ajax driven form
Posted: Fri Aug 15, 2008 2:08 pm
by ell0bo
Here is what I was trying to say, but now in code. I'm just grabbing a snippet quick, but this should be able to give you most of what you need to know...
Code: Select all
<script>
function uploadTrack(id){
smarty.addData('check', 1);
smarty.addData('id', id);
smarty.ajax('/file_upload.php', function(dat){
e = document.getElementById(id+'_gage');
while(e.hasChildNodes())
e.removeChild(e.firstChild);
if ( dat['progress'] == '-1' ){
$(e).html('ERROR');
e.className = 'error'
}
else if ( dat['progress'] == '100' ){
$(e).html('UPLOADED');
e.className = 'finished'
}
else{
/*
var p = dat['progress'];
var t = document.createElement('div');
if ( p < 25 ){
t.className = 'quarter';
}
else if ( p < 50 ){
t.className = 'midway';
}
else if (p < 75 ){
t.className = 'almost';
}
else{
t.className = 'last';
}
t.style.width = p+'px';
e.appendChild(t);
*/
$(e).html('UPLOADING...');
e.className = 'going'
setTimeout(function(){uploadTrack(id)}, 2000);
}
}, 1);
}
</script>
<style type="text/css">
@import url("/styles/base.css");
@import url("/styles/front.css");
@import url("/styles/forms.css");
* {margin: 0px; padding: 0px; border: none; font-size: 12px; line-height: 14px;}
input { border: 1px solid black;}
.quarter, .midway, .almost, .last, .error, .finished, .going{
display: block; height: 100%; background-color: black;
}
.going{
background-color: yellow;
}
.finished{
background-color: #33ff33;
}
.error{
background-color: #ff3333;
}
</style>
</head>
<body>
<form onsubmit = "this.target = '<? echo $name; ?>_targ';
uploadTrack('<? echo $name; ?>');"
enctype="multipart/form-data" action="/file_upload.php"
id = "<? echo $name; ?>_form" method="POST">
<input type="hidden" name="file_mask" value="<? echo $name; ?>">
<input id="<? echo $name; ?>" name="<? echo $name; ?>" type='file'><br>
<input type="submit" value="Upload File" style="width: 100px; float: left;">
<span id="<? echo $name; ?>_gage" style="width: 100px; display: block; height: 18px;
margin-left: 110px; border-bottom: 1px solid black;"></span><br>
<iframe id="<? echo $name; ?>_targ" name="<? echo $name; ?>_targ"
style="display: none;"></iframe>
</form>
</body>
</html>
<?php
}
elseif ( isset($_POST['file_mask']) ){
$id = urldecode($_POST['file_mask']);
$file = $_FILES[$id];
$tmp = filePath('tmp', $id.'.dat', true);
$fh = fopen($tmp, 'w');
fwrite($fh, serialize($file));
move_uploaded_file($file["tmp_name"], filePath('tmp', $id.'.up', true)) ;
print_r($_FILES);
}
elseif ( isset($_POST['check']) ){
$id = urldecode($_POST['id']);
$arr = array();
if ( $fp = @fopen(filePath('tmp', $id.'.dat', true), "rb") ){
$file = unserialize(fread($fp,1000));
if ( $file['error'] > 0 ){
$arr['progress'] = -1;
$arr['error'] = $file['error'];
}
else{
$current_size = @filesize(filePath('tmp', $id.'.up', true));
$arr['progress'] = intval(($current_size / $file['size'] * 100));
}
}
else{
$arr['progress'] = 50;
}
echo json_encode( array('valid' => 1, 'data' => $arr) );
}
smarty is an in house ajax handler i developed, it's basically a wrapper around jquery's ajax stuff. This if file_upload.php, so it calls itself when it submits, and when you are checking for status. You could prolly write it a little more elegantly, but this is what I came up with.
Re: File uploads on an ajax driven form
Posted: Fri Aug 15, 2008 6:28 pm
by kendall
cool