$_FILES empty after AJAX upload - javascript

I'm developing a simple script to upload a file through AJAX but after form submission, the variable $_FILES is completely empty, although the file exists within php://input, but with no simple way to extract only the file. Anyone knows the reason and/or solution to this problem?
I've checked all the common solutions.
enctype="multipart/form-data"
rights to temp folder
form-tags closing
doublequotations
and the output of the file-input in JS
Nothing has solved my problem.
RED
This is NOT jquery, and I haven't found a duplicate in 24h. So please don't mark as duplicate unless you're sure it is one.
HTML
<form action="upload.php" method="POST" enctype="multipart/form-data" id="testf">
<input type="file" name="file" accept=".jpg">
<input type="submit" value="Skicka">
</form>
JavaScript
let data = document.querySelector("#testf");
data.onsubmit = function() {
var http = new XMLHttpRequest();
http.open("upload.php", data.action);
http.onreadystatechange = function () {
console.log(http.response);
}
http.setRequestHeader("Content-type", data.enctype);
http.send(new FormData(data));
event.preventDefault();
return false;
}
PHP
<?php
var_dump($_FILES);
?>
This should print the contents of my file, but
array(0) {}
is all I get.
Request payload is:
------WebKitFormBoundaryZVGq8suqFUUSFDtW
Content-Disposition: form-data; name="file"; filename="david.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryZVGq8suqFUUSFDtW--

You have a problem with your JavaScript method XMLHttpReqest. It takes at least two parameters: Method and url.
Full parameters are:method, url, async, user, password
Change your code from:
http.open("upload.php", data.action);
To:
http.open("post", data.action );
Update:
Also remove
http.setRequestHeader("content-type", "multipart/form-data")
Form data already sets its headers for content-type.

Did you checked if memory limit is set to -1 or high enough in php.
Sometime on Apache or iis server, there is also a block on high file uploads.

Related

$_POST array empty in php after submission of a form using a formData

I've seen several posts about the issue but none of them solved my problem. I'm working with XAMPP and I have an html index.html and a php remote.php in the same folder.
The formData which I want to send to the php is created using a form (basic_form) in javascript. It resulted to be well constructed, since console.log(...formData); printed Array [ "mode", "basic" ], Array [ "file", File ] as expected, which are the string and the input file.
But unfortunately in the php the command print_r($_POST); outputs only Array() and also the command var_dump($_POST); outputs array(0){}. So it seems that the content of the form is not passed to the php.
Here it is the html form:
<body>
<div>
<form name="basic_form" enctype="multipart/form-data" action="remote.php" method="post">
<input type="text" id="mode" name="mode" value="basic"/>
<input type="file" id="file" name="file"/>
<input type="submit" id="submit_basic_input" name="submit_basic_input" value="Submit"/>
</form>
</div>
</body>
Here the javascript to submit the form:
<script>
var basic_form = document.forms["basic_form"];
basic_form.addEventListener('submit', e => {
e.preventDefault();
const url = 'remote.php';
const formData = new FormData(basic_form);
fetch(url, {
method: 'POST',
body: formData
}).then(response => {
console.log(response);
if(response["status"] == 200)
location.replace(response["url"]);
});
});
</script>
Here the php to print the content of form:
<?php
var_dump($_POST);
$datapost = $_POST;
print_r($datapost);
print($datapost["mode"]);
?>
First, you call fetch which makes a POST request
When you get a response, you log the response object (which doesn't hold anything all that useful, in particular the body of the response will show up as a readable stream and not a string).
That response does show array(1) { ["mode"]=> string(5) "basic" } Array ( [mode] => basic ) basic though, you can see it using the Network tab of the browser's developer tools.
After logging the response you set location.replace(response["url"]); which makes a GET request (to the same URL) and navigates the browser to it.
The GET request is a different request and does not have the request body from the POST request from it.
Since it is a different request, it gets a different response and now $_POST is an empty array.
If you want to navigate to the response then get rid of the JavaScript. Just make the POST request with the form and let the browser render the resulting page.
If you want to use Ajax to make the request then:
Don't immediately navigate away from the page
Do something useful with the response (starting by calling response.text() to get the data out of the response body and then perhaps using createElement, appendChild and friends to add the data to the current document)

Java Script - JSON in hidden form field

Is it possible to send POST with JSON content, which comes from hidden form field?
My form looks like this:
<form method="POST" name="form0" action="https://my_url/comment/id?Id=5">
<input type="hidden" name="id" id="inputField" value='{"number":5,"content":"aaaa"}'/>
</form>
And I would like to send POST with {"number":5,"content":"aaaa"} as JSON not as string.
If I use:
document.forms[i].submit();
it is send as a string.
An HTML form can only encode data as application/x-www-form-urlencoded, multipart/form-data or text/plain (the latter is not of any practical use).
Your existing code will encode the JSON within that.
If you want to send an application/json encoded form body, then you'll need to use XMLHttpRequest or fetch.
For example:
var xhr = new XMLHttpRequest();
xhr.open("POST", "/path/to/handler");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({"number":5,"content":"aaaa"}));
Yes, you can do so. But you'd need to decode this on the server side, as it will just be transported as string.
Using jQuery, this would be super easy to accomplish:
$.post('https://my_url/comment/id?Id=5', {"number":5,"content":"aaaa"});
You could even pass a callback to react to whatever is returned:
$.post('https://my_url/comment/id?Id=5', {"number":5,"content":"aaaa"}, function (response){
// Do something cool here.
});

Storing information from php script

I m working on an html page that contains a form allowing users to enter their informations and upload files. all informations will be inserted in Mysql database.
in Javascript, im using XMLHttpRequest to send the files to the server and "upload.php" to rename (to avoid dupplicated names) and move them in the upload directory.
For better user experience, this will be done before submitting the whole form.
My question is : How can i store the new filenames (defined in upload.php)to use them in the form submission "submit.php"?
the reason for this is that in "submit.php", i insert first the user informations in "user" table and then select the "user_id" (auto increment) that will be inserted with filenames in the "files" table.
Could php sessions be an approach to do this ? is there another way? Thanks for your help
html:
<form action="submit.php" method="post" id="submitform">
<div>
<--!user info part1-->
</div>
<div id="filesContainer" class="eltContainer">
<input type="file" id="filesList" multiple>
</div>
<div>
<--!user info part2-->
</div>
javascript:
var fd = new FormData()
var xhr = new XMLHttpRequest()
for (var i=0,nb = fichiers.length; i<nb; i++) {
var fichier = fichiers[i]
fd.append(fichier.name,fichier)
}
xhr.open('POST', 'upload.php', true)
upload.php :
<?php
foreach($_FILES as $file){
$filename = date('Y') . date('m') . date('d') . date('H') . date('i') . basename($_FILES[$file]['name']);
move_uploaded_file( $file['tmp_name'],"../upload_dir/" .$filename);
}
exit;
I would consider using something like md5 for unique filenames.
Nevertheless you can push filenames into some array, and than return those filenames, as a result of post request, and put them back into some input field.
To retrieve the response simply add this lines to your code below open
xhr.onreadystatechange = function {
// If the request completed and status is OK
if (req.readyState == 4 && req.status == 200) {
// keep in mind that fileNames here are JSON string
// as you should call json_encode($arrayOfFilenames)
// in your php script (upload.php)
var fileNames = xhr.responseText;
}
}
If you'd like consider using a simple library for AJAX requests, like axios. It's promise based HTTP client for the browser, really simple to use and saves you some time and effort cause you don't have to memorize all this stuff you and I have just written.
This is one approach, but I think you can use $_SESSION as well, and it's perfectly valid. My guess is you don't have logged in user at this point, so my idea is as follows:
put filenames into the $_SESSION
use db transactions - as #Marc B suggested - to connect files with
user
if there were no errors just remove filenames from $_SESSION, if there was some, just redirect the user back to the form (possibly with some info what went wrong), and this way he doesn't have to reupload files, cause you have filenames still in $_SESSION

$_POST and $_FILES empty after AJAX file upload

I am new to web development, and the latest problem I have been having is ajax file uploading...
Right now I have two HTML input fields; a file input and a button.
<input type="file" name="Frame" id="Frame_"/>
<input type="button" name="FrameButton" id="FrameButton_" value="UPLOAD"/>
After the button is clicked I then call a function that has the following code..
var frame = document.getElementById('Frame_');
var frameImg = frame.files[0];
var form_data = new FormData();
form_data.append('frame', frameImg);
jQuery.ajax({
url : './handler.php',
type : 'post',
data : form_data
contentType : false,
processData : false,
success : alert("Frame Uploaded")
});
When I var_dump() the $_POST and $_FILES array it shows both arrays as empty. This is despite the "Request Payload" in Chrome Dev reading
Content-Disposition: form-data; name="frame"; filename="GoldFrame.jpg"
Content-Type: image/jpeg
In which I am under the impression that this means the information of the file that I select on the front end is being successfully "post"ed to my handler.php file. Is this a wrong interpretation?
Either way, could someone please give me an answer to my problem? Or atleast point to a resource that might have my answer? There seem to be many similar questions along the same lines, but I haven't seen one that has a solid answer.
I have used iframes for this kind of thing in the past, but that seems like a really hacky method, and I would like to have the flexibility to use ajax for this kind of task in the future.
Help is appreciated.
Try this.
Form (index.html)
<form id="uploadForm">
<input type="file" name="frame" />
<input type="submit" value="UPLOAD" />
</form>
Script (script.js)
$("#uploadForm").on('submit',(function(e) {
e.preventDefault();
$.ajax({
url: "handler.php",
type: "POST",
data: new FormData(this),
contentType: false,
processData: false,
success: function(data){
console.log(data);
}
});
}));
Server Side (handler.php)
<?php
var_dump($_FILES);
When posting a file and/or text, This set of codes is also useful for debugging purposes. You can use this to see if your post is too large as that too can cause empty $_POST & $_FILE arrays even though its posted.
print_r($_POST); /* Looks at the $_POST array. (Will be empty if $_SERVER['CONTENT_LENGTH']/1000000 is greater than ini_get('post_max_size') ) */
echo "<br>";
print_r($_FILES); /* Looks at the $_FILES array. It will also show you the file size in bytes: divide it by 1 million (1000000) to get the megabytes value. (Will be empty if $_SERVER['CONTENT_LENGTH']/1000000 is greater than ini_get('post_max_size') ) */
echo "<br>" . $_SERVER['CONTENT_LENGTH']/1000000 ; /* This will give you the size in megabytes of your $_POST */
echo "<br>" . ini_get('post_max_size'); /*This will show you the post_max_size in your php.ini file*/
echo "<br>" . ini_get('upload_max_filesize'); /*This will show you the upload_max_filesize in your php.ini file*/
// phpinfo(); // You might not need this function but you can use it for more information on your php.ini file. It can help you find its location (for maybe editing purposes) and view its data.
Are you var_dump()-ing your $_FILES/$_POST arrays in the handler.php file?
If you are trying to dump these variables in the file that has the ajax call, it won't work because AJAX is making the front-end call, and the files/post variables are server side variables ... which means only the handler.php file will have these variables available.
Try adding the var_dump() call in handler.php, and output that result in the ajax call, and I am hopeful you will see the results you are looking for.

Unable to get file in $_FILES but getting in $_SERVER

(as asked by so to clarify why my question is not duplicated of suggested post )
IMHO My question is not duplicate to that question since
I am suing JavaScript and Ajax which linked question does not
though I have tried solution of that post which doesn't worked
I am using ajax and to make ajax request I am using javaScript
HTML
<input id="file" type="file" name="our-file" />
<input type="button" value="Upload" id="upload-button" />
Js
var inputFile = document.getElementById("file"),
uploadButton = document.getElementById("upload-button");
uploadButton.onclick = function () {
console.log(inputFile.files[0])
var file = inputFile.files[0];
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = stateHandler;
httpRequest.open("POST", "upload.php", true);
httpRequest.setRequestHeader("X-File-Name", file.name);
httpRequest.send(file)
function stateHandler() {
var status = {
"httpRequest ready state": httpRequest.readyState,
"status": httpRequest.status,
"httpRequest responseText":httpRequest.responseText
};
console.log(status);
console.log(httpRequest.responseText);
}
}
now when I try to get uploaded file via $_FILES I get empty array but
$_SERVER have complete file information, is it because I have only sent header not file itself ?
screeshot of my output with $_SERVER http://i.stack.imgur.com/1GMdh.png
screen shot of my output with $_FILES http://i.stack.imgur.com/IECUt.png
thanks and I don't want jquery suggestion (I think its good to know language before framework developed by it :)
You are sending raw file data. You aren't sending a multipart/form-data encoded request, so it won't be processed as regular form data (so $_FILES and $_POST won't be populated).
Create a form data object.
var formData = new FormData();
Put the file information in that:
formData.append("myFile", inputFile.files[0]);
Send that:
request.send(formData);

Categories

Resources