Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES...?

JavaScript and client side scripting.

Moderator: General Moderators

Post Reply
Wolf_22
Forum Contributor
Posts: 159
Joined: Fri Dec 26, 2008 9:43 pm

Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES...?

Post by Wolf_22 »

Problem:
I've created an AJAX file upload that works wonderfully with jQuery 1.11.x but when I switch over to a local version of jQuery 1.4.x (a version I'm forced to use in production), I begin to have issues with getting PHP to acknowledge the uploaded file details.

With jQuery 1.11.x, I can see var_dump($_FILES) output as expected and it's beautiful! :)

...but with jQuery 1.4.x, I cannot and it's giving me a serious headache. Instead, the AJAX post occurs as expected per-Firebug's POST details but the RESPONSE details show only the markup I started with. Nothing new or changed.

Code (you should be able to copy-and-paste-and-run as-is):

Code: Select all

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Ajax Upload Test</title>
    </head>
    <body>
        <div id="wrapper">
            <div id="header"></div>
            <div id="left"></div>
            <div id="right">
				<form method="post" enctype="multipart/form-data">
					<input id="file" type="file" name="file"/>
				</form>
                <div id="response">
                <?php
                    print '<pre>';
                    var_dump($_FILES);
                    print '</pre>';
                ?>
                </div>
            </div>
            <div id="footer"></div>
        </div>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
		<!--<script type="text/javascript" src="jquery_1.4.4.js"></script>-->
        <script type="text/javascript">
			var input = $("#file");
			var formdata = false;

			if(window.FormData){
				formdata = new FormData();
			}

			input.bind("change", function (evt) {
				var i = 0, len = this.files.length, reader, file;

				for(;i<len;i++){
					file = this.files[i];

					//if (!!file.type.match(/image.*/)){
					if (!!file.type.match(/text.*/)){
						if ( window.FileReader ) {
							reader = new FileReader();
							reader.onloadend = function(e){};
							reader.readAsDataURL(file);
						}

						if(formdata){
							formdata.append("text", file);
							formdata.append("extra",'extra-data');
						}

						if(formdata){
							//jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
							jQuery.ajax({
								url: "index.php",
								type: "POST",
								data: formdata,
								processData: false,
								contentType: false,
								success: function (res) {
									console.log(res);
									$('#response').empty();
									$('#response').html($(res).find('#response').html());
								}
							});
						}

					}else{
						alert('Not a vaild file type.');
					}
				}
				evt.preventDefault();
			});
		</script>
    </body>
</html>
Conclusion:
It's as if the PHP isn't able to grab / acquire / acknowledge the file payload and so when I try to use var_dump($_FILES), it just keeps coming up as an empty PHP array (which implies that either PHP isn't seeing the details or else my AJAX is inadvertently refreshing the DIV with a brand new index.php request, absent of the initial AJAX call details). Does that sound right?

Any insight into this would be very appreciated. It's really got me banging my head.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by requinix »

You may need to specify the contentType (multipart/form-data).

Is the file showing up in $_POST?
What did Firebug show for the request?
Wolf_22
Forum Contributor
Posts: 159
Joined: Fri Dec 26, 2008 9:43 pm

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by Wolf_22 »

You may need to specify the contentType (multipart/form-data).
If you're implying that having it in the form element isn't enough, I went ahead and added it in the jQuery.ajax() properties, too, as follows:
[syntax]contentType: 'multipart/form-data',[/syntax]

...and I get the same results back in Firefox: Firebug reports a successful 200 return code upon post but the response only returns the original index.php markup. (In other words, since I initiate .ajax() from index.php, I get that same page back--despite appearing to successfully deliver the post payload.
Is the file showing up in $_POST?
No, it isn't. Every time I initialize the ajax function, all I ever get back is just the original index.php page--nothing else. The arrays ($_POST and $_FILES) always return an empty array.
What did Firebug show for the request?
Here's the Response Headers being sent:
[syntax]HTTP/1.1 200 OK
Date: Mon, 08 Sep 2014 23:54:45 GMT
Server: Apache/2.2.22 (Win32) mod_ssl/2.2.22 OpenSSL/0.9.8k PHP/5.2.9-2
X-Powered-By: PHP/5.2.9-2
Content-Length: 3874
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
X-Pad: avoid browser bug[/syntax]

...and the Response Headers:
[syntax]POST /projects/ajax_file_upload/index.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: false
X-Requested-With: XMLHttpRequest
Content-Length: 293
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache[/syntax]

Firebug shows the test.txt file being submitted successfully (I see a 200 OK in the "Status" column). I also see the file being sent:
[syntax]-----------------------------12435295776740
Content-Disposition: form-data; name="text";
filename="test.txt" Content-Type: text/plain

-----------------------------12435295776740
Content-Disposition: form-data;
name="extra" extra-data
-----------------------------12435295776740--[/syntax]

...which is what I saw when I used the latest jQuery--which worked. The response that is returned is just the original index.php markup / page, with nothing showing up where I have var_dump($_POST) or var_dump($_FILES) (they still show array(0), etc.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by requinix »

In the request headers there's

Code: Select all

Content-Type: false 
That could easily be the problem. Are those headers from the new code with that contentType change? If not, what does it all look like with the change?
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by Celauran »

jQuery.ajax was completely re-written in 1.5. 1.5 is exactly where this code starts working. 1.4.4 fails, 1.5 through 1.11.1 works fine. As requinix pointed out, 1.4.x sets the content-type to "false" whereas later versions, with contentType:false, the actual request header contains "multipart/form-data; boundary=whatever".
Wolf_22
Forum Contributor
Posts: 159
Joined: Fri Dec 26, 2008 9:43 pm

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by Wolf_22 »

requinix wrote:In the request headers there's

Code: Select all

Content-Type: false 
That could easily be the problem. Are those headers from the new code with that contentType change? If not, what does it all look like with the change?
I changed the code to be the following:

Code: Select all

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Ajax Upload Test</title>
    </head>
    <body>
        <div id="wrapper">
            <div id="header"></div>
            <div id="left"></div>
            <div id="right">
                                <form method="post" enctype="multipart/form-data">
                                        <input id="file" type="file" name="file"/>
                                </form>
                <div id="response">
                <?php
                    print '<pre>';
                    var_dump($_FILES);
                    print '</pre>';
                ?>
                </div>
            </div>
            <div id="footer"></div>
        </div>
        <script type="text/javascript" src="jquery_1.4.4.js"></script>
        <script type="text/javascript">
                        var input = $("#file");
                        var formdata = false;

                        if(window.FormData){
                                formdata = new FormData();
                        }

                        input.bind("change", function (evt) {
                                var i = 0, len = this.files.length, reader, file;

                                for(;i<len;i++){
                                        file = this.files[i];

                                        //if (!!file.type.match(/image.*/)){
                                        if (!!file.type.match(/text.*/)){
                                                if ( window.FileReader ) {
                                                        reader = new FileReader();
                                                        reader.onloadend = function(e){};
                                                        reader.readAsDataURL(file);
                                                }

                                                if(formdata){
                                                        formdata.append("text", file);
                                                        formdata.append("extra",'extra-data');
                                                }

                                                if(formdata){
                                                        //jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
                                                        jQuery.ajax({
                                                                url: "index.php",
                                                                type: "POST",
                                                                data: formdata,
                                                                processData: false,
                                                                contentType: "multipart/form-data",
                                                                success: function (res) {
                                                                        console.log(res);
                                                                        $('#response').empty();
                                                                        $('#response').html($(res).find('#response').html());
                                                                }
                                                        });
                                                }

                                        }else{
                                                alert('Not a vaild file type.');
                                        }
                                }
                                evt.preventDefault();
                        });
                </script>
    </body>
</html>
The Firebug Post details are as follows:
-----------------------------118961866025156
Content-Disposition: form-data; name="text"; filename="test.txt"
Content-Type: text/plain

-----------------------------118961866025156
Content-Disposition: form-data; name="extra"

extra-data
-----------------------------118961866025156--
The Firebug Response details are as follows:

Code: Select all

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Ajax Upload Test</title>
    </head>
    <body>
        <div id="wrapper">
            <div id="header"></div>
            <div id="left"></div>
            <div id="right">
                                <form method="post" enctype="multipart/form-data">
                                        <input id="file" type="file" name="file"/>
                                </form>
                <div id="response">
                <pre>array(0) {
}
</pre>                </div>
            </div>
            <div id="footer"></div>
        </div>
        <script type="text/javascript" src="jquery_1.4.4.js"></script>
        <script type="text/javascript">
                        var input = $("#file");
                        var formdata = false;

                        if(window.FormData){
                                formdata = new FormData();
                        }

                        input.bind("change", function (evt) {
                                var i = 0, len = this.files.length, reader, file;

                                for(;i<len;i++){
                                        file = this.files[i];

                                        //if (!!file.type.match(/image.*/)){
                                        if (!!file.type.match(/text.*/)){
                                                if ( window.FileReader ) {
                                                        reader = new FileReader();
                                                        reader.onloadend = function(e){};
                                                        reader.readAsDataURL(file);
                                                }

                                                if(formdata){
                                                        formdata.append("text", file);
                                                        formdata.append("extra",'extra-data');
                                                }

                                                if(formdata){
                                                        //jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
                                                        jQuery.ajax({
																traditional: true,
																cache: false,
                                                                url: "index.php",
                                                                type: "POST",
                                                                data: formdata,
                                                                processData: false,
                                                                contentType: "multipart/form-data",

                                                                success: function (res) {
                                                                        console.log(res);
                                                                        $('#response').empty();
                                                                        $('#response').html($(res).find('#response').html());
                                                                }
                                                        });
                                                }

                                        }else{
                                                alert('Not a vaild file type.');
                                        }
                                }
                                evt.preventDefault();
                        });
                </script>
    </body>
</html>
(Basically the original index.php file I started with.)

The Request Headers:
POST /projects/ajax_file_upload/index.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data
X-Requested-With: XMLHttpRequest
Content-Length: 296
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
The Response Headers:
HTTP/1.1 200 OK
Date: Tue, 09 Sep 2014 04:18:21 GMT
Server: Apache/2.2.22 (Win32) mod_ssl/2.2.22 OpenSSL/0.9.8k PHP/5.2.9-2
X-Powered-By: PHP/5.2.9-2
Content-Length: 4037
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: text/html
X-Pad: avoid browser bug
Side Note:
I was able to get *some* content back using var_dump(file_get_contents('php://input')) at the top of the page before the opening HTML tag (which I didn't include in the code snippet above because I didn't think it was what I wanted) but in so doing, I retrieved the following (only visible in Firebug's NET panel--I couldn't see it in the final markup after my POST was executed):
-----------------------------305083071515052
Content-Disposition: form-data; name="text"; filename="test.txt"
Content-Type: text/plain
-----------------------------305083071515052
Content-Disposition: form-data; name="extra"
extra-data
-----------------------------305083071515052--
That's not what I'm hoping for though because $_FILES is always empty... Any thoughts?
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by Celauran »

You're missing the boundary in your content-type request header.
Wolf_22
Forum Contributor
Posts: 159
Joined: Fri Dec 26, 2008 9:43 pm

Re: Trying to use jQuery 1.4.x: AJAX file upload w/ $_FILES.

Post by Wolf_22 »

Celauran wrote:You're missing the boundary in your content-type request header.
Ah, you mean the "whatever", right? Well, I added it (current code):

Code: Select all

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Ajax Upload Test</title>
    </head>
    <body>
        <div id="wrapper">
            <div id="header"></div>
            <div id="left"></div>
            <div id="right">
				<form method="post" enctype="multipart/form-data">
					<input id="file" type="file" name="file"/>
				</form>
                <div id="response">
					<?php 
						print '<pre>';
						var_dump($_FILES);
						print '</pre>';
					?>
				</div>
            </div>
            <div id="footer"></div>
        </div>
        <script type="text/javascript" src="jquery_1.4.4.js"></script>
        <script type="text/javascript">
                        var input = $("#file");
                        var formdata = false;

                        if(window.FormData){
                                formdata = new FormData();
                        }

                        input.bind("change", function (evt) {
                                var i = 0, len = this.files.length, reader, file;

                                for(;i<len;i++){
                                        file = this.files[i];

                                        //if (!!file.type.match(/image.*/)){
                                        if (!!file.type.match(/text.*/)){
                                                if ( window.FileReader ) {
                                                        reader = new FileReader();
                                                        reader.onloadend = function(e){};
                                                        reader.readAsDataURL(file);
                                                }

                                                if(formdata){
                                                        formdata.append("text", file);
                                                        formdata.append("extra",'extra-data');
                                                }

                                                if(formdata){
                                                        //jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
                                                        jQuery.ajax({
																traditional: true,
																cache: false,
                                                                url: "index.php",
                                                                type: "POST",
                                                                data: formdata,
                                                                processData: false,
                                                                contentType: "multipart/form-data; boundary=whatever",

                                                                success: function (res) {
                                                                        console.log(res);
                                                                        $('#response').empty();
                                                                        $('#response').html($(res).find('#response').html());
                                                                }
                                                        });
                                                }

                                        }else{
                                                alert('Not a vaild file type.');
                                        }
                                }
                                evt.preventDefault();
                        });
                </script>
    </body>
</html>
So with that added, I executed the ajax() call and received the following results:

Firebug Post Details:
-----------------------------1015285086226
Content-Disposition: form-data; name="text"; filename="test.txt"
Content-Type: text/plain

-----------------------------1015285086226
Content-Disposition: form-data; name="extra"

extra-data
-----------------------------1015285086226--
Firebug Response Details:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax Upload Test</title>
</head>
<body>
<div id="wrapper">
<div id="header"></div>
<div id="left"></div>
<div id="right">
<form method="post" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
</form>
<div id="response">
<pre>array(0) {
}
</pre> </div>
</div>
<div id="footer"></div>
</div>
<script type="text/javascript" src="jquery_1.4.4.js"></script>
<script type="text/javascript">
var input = $("#file");
var formdata = false;

if(window.FormData){
formdata = new FormData();
}

input.bind("change", function (evt) {
var i = 0, len = this.files.length, reader, file;

for(;i<len;i++){
file = this.files;

//if (!!file.type.match(/image.*/)){
if (!!file.type.match(/text.*/)){
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function(e){};
reader.readAsDataURL(file);
}

if(formdata){
formdata.append("text", file);
formdata.append("extra",'extra-data');
}

if(formdata){
//jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
jQuery.ajax({
traditional: true,
cache: false,
url: "index.php",
type: "POST",
data: formdata,
processData: false,
contentType: "multipart/form-data; boundary=whatever",

success: function (res) {
console.log(res);
$('#response').empty();
$('#response').html($(res).find('#response').html());
}
});
}

}else{
alert('Not a vaild file type.');
}
}
evt.preventDefault();
});
</script>
</body>
</html>


Request Headers:
POST /practice/jquery/index.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=whatever
X-Requested-With: XMLHttpRequest
Content-Length: 290
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache


Response Headers:
HTTP/1.1 200 OK
Date: Tue, 09 Sep 2014 16:21:36 GMT
Server: Apache/2.2.22 (Win32) PHP/5.3.13
X-Powered-By: PHP/5.3.13
Content-Length: 3844
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html


...still nothing in $_FILES but if you guys are right, it's likely because the boundary isn't being added. Am I going about adding it incorrectly? How do I add the boundary???
Post Reply