Forum Moderators: open

Message Too Old, No Replies

Encoding a file/input for AJAX upload?

Existing script works great except with file inputs.

         

JAB Creations

7:13 pm on Jan 20, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm trying to determine how to upload an image via AJAX. When I prevent non-AJAX forms from submitting I reconstruct the request with the first function below and then execute it with the following code. This has worked great up until the point today when I began experimenting with file uploads.

There are two things that I'm pretty sure I have to do though not sure about the approach. First in the function ajax_post_parameters I need to add the file-input type which I have just like the text-input and while the server (using PHP) saw the $_POST['file'] was set there was no corresponding $_FILE['file'].

I've also messed with setting "application/x-www-form-urlencoded" versus "multipart/form-data" and the former works in my non-AJAX prototype.

I'm not really sure what I need to do here specifically though those are the two general things I've been messing with. Thoughts please?

- John

// Example Execution

var param = ajax_post_parameters('form_image');
var result = ajax_post(path+'upload_path/',param);


// AJAX Parameters
function ajax_post_parameters(id)
{
if (document.getElementById(id))
{
var form = document.getElementById(id);
var param = 'ajax=1&';

for (var i=0;i<form.elements.length;i++)
{
if (form.elements[i].name!=undefined && form.elements[i].name!='' && !form.elements[i].getAttribute('disabled'))
{
if (form.elements[i].type=='checkbox' || form.elements[i].type=='radio') {if (form.elements[i].checked==true)
{param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}}
else if (form.elements[i].type=='text') {param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}
else if (form.elements[i].type=='password') {param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}
else if (form.elements[i].type=='hidden') {param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}
else if (form.elements[i].nodeName=='select') {param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}
else if (form.elements[i].type=='textarea') {param += form.elements[i].name+'='+encodeURIComponent(censor(form.elements[i].value))+'&';}
}
}
param += option.name+'=1';
}
else {alert('Error: no form with the id of \''+id+'\' was found.');}

var parameters = param.replace(/\\/g,'\\');
return parameters;
}

//AJAX POST
function ajax_post(url,parameters)
{
var http = false;
if (window.XMLHttpRequest)
{
http = new XMLHttpRequest();
if (http.overrideMimeType) {http.overrideMimeType('text/html');}
http.overrideMimeType('text/xml');
}
else if (window.ActiveXObject)
{
try {http = new ActiveXObject('Msxml2.XMLHTTP')}
catch (e) {try{http = new ActiveXObject('Microsoft.XMLHTTP')} catch (e){}}
}

if (!http) {var result = 'Error: your browser does not support AJAX.'; browser_upgrade();}
else
{
http.open('POST',url,false);
var o800 = navigator.userAgent.split('8.0 ');

if (o800.length!=2)
{
http.setRequestHeader('Content-type','application/x-www-form-urlencoded');
http.setRequestHeader('Content-length',parameters.length);
http.setRequestHeader('Connection','close');
}
http.send(parameters);
if (http.readyState==4) {var result = http.responseText;}
}
return result;
}

coopster

5:26 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Use an iframe. I modified a webkit version that I found awhile back. Maybe this will help.
[webtoolkit.info...]

JAB Creations

5:42 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks Coopster, I came across that page while doing a lot of searching and unfortunately it only uploads the text value of the form.

I decided to go with an iframe which is forcing me to now figure out how to append the XHTML 1.1 doctype. On the bright side it works, I just have to deal with the fact that amending a doctype is a pain.

- John

coopster

7:05 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



it only uploads the text value of the form


?
I use it all the time to upload files. Works like a charm.

JAB Creations

7:23 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Again thanks however if you look at the source code it uses innerHTML to create an iframe which is odd because I looked at the context menu in Firefox and didn't see any of the associated menus for frames. I can live with the iframe as soon as I finish validating one more thing and will post my findings in the HTML forums later.

- John

coopster

8:02 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



It creates a new div element with a unique id attribute. Then it uses innerHTML to create an iframe in that div. You pass it the form and optionally an object with two optional functions. Actually, I just realized that the HTML on that page and the actual JS in the demo differ slightly. My version looks a lot more like this one that has that iframe code embedded:

[webtoolkit.info...]

I pass the form object and the optional object functions in my code. Something like so ...

return AIM.submit( 
this, // which is my form
{
'onStart' : function()
{
},
'onComplete' : function(response)
{
}
}


Fill in the custom functions with what you need/desire.

JAB Creations

9:07 pm on Jan 21, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It's still not AJAX and I'm okay with that. I was reading about XMLHttpRequest2 [w3.org] and came across the FileAPI [dev.w3.org] so unless I've missed something I think using AJAX to upload the file as an incontestable axiom just isn't possible at this point. I suppose by the end of this decade it may be viable though the need for some form of viable execution exists now.

I've spent half of my day working to make the iframe validate with the XHTML 1.1 doctype [webmasterworld.com]. Code-wise I've been able to make it keyboard accessible (and have the file-input element completely styled in all browsers) so I'm only stuck on this last validation issue. I'm bent on figuring out this validation issue because I simply haven't been able to find an AJAX/non-iframe/non-Flash way to pull this off. Thanks for your suggestion. :)

- John