AJAX form upload not grabbing file - AJAX/jQuery - javascript

I am not sure if I am grabbing the file from the form correctly in the following jQuery code which uses AJAX to upload a file.
function uploadFile() {
console.log("uploading");
var form = document.getElementById('fileForm');
var fileSelect = document.getElementById('browseInput');
console.log("check1");
var file = fileSelect.files;
var formData = new FormData();
formData.append('FileInput', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'default/ParseExcel', true);
xhr.send(formData);
console.log("complete");
}
I get the error that file is undefined on line 39 (which is the formData.append() line in the code above.
I'm not sure if I am supposed to be grabbing the file form the form variable or from the fileSelect variable.
The full error:
TypeError: Argument 2 of FormData.append does not implement interface Blob.
HTML code:
<form enctype="multipart/form-data"
method="POST"
id="fileForm"
onsubmit="uploadFile()"
style="display:inline-block;">
<input id="browseInput" type="file" name="FileInput" style="display: none"/>
<label for="upload-click-handler"></label>
<input id="upload-click-handler" type="text" readonly />
<button id="submitFormButton" type="submit" style="display: none"></button>
</form>

Try this:
function uploadFile(e) {
e.preventDefault();
var formElement = document.getElementById('fileForm');
var formData = new FormData(formElement);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'pack.php', true);
xhr.send(formData);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form enctype="multipart/form-data" method="POST" id="fileForm" onsubmit="uploadFile(event)">
<input id="browseInput" type="file" name="FileInput" />
<button id="submitFormButton" type="submit">Submit</button>
</form>
Output using var_dump($_FILES);
array (size=1)
'FileInput' =>
array (size=5)
'name' => string '3400.JPG' (length=8)
'type' => string 'image/jpeg' (length=10)
'tmp_name' => string 'E:\wamp\tmp\php38E2.tmp' (length=23)
'error' => int 0
'size' => int 164319

Related

Javascript formData array returns empty

I have an issue with my AJAX formData object. If select a file in the input and I send this with AJAX the array is empty. I hope somebody can help me with this. Below my code
HTML and JavaScript
<form method="post" id="quoteform">
<input type="file" name="uploadfile" id="quote"/>
<input type="submit" value="upload"/>
</form>
<script type="text/javascript">
document.getElementById("quoteform").addEventListener("submit", function(){
var files = document.getElementById("quote").files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i]
formData.append('files[]', file);
}
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "linktophpfile.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send('upload='+formData);
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
alert(this.responseText);
}
}
event.preventDefault();
});
</script>
PHP
<?php
if(isset($_POST['upload'])){
print_r($_FILES);
}
?>
The PHP file returns
Array
(
)
when you upload files then you can't use application/x-www-form-urlencoded you have to use multipart/form-data
you shouldn't mix strings with formData send('upload='+formData) it will only result in you uploading a string equal to upload=[Object object]
you should instead just send the formData and let the XHR or Fetch handle the content-type for you automatically.
If you want an array then i presume you also want the attribute mulitple? You could always add in the required and accept="image/*, .txt" for good measure
You don't manually have to add in all files to a formdata if you just use the first constructor argument that accepts a form element, everything from the form will be added
<form method="POST" action="https://httpbin.org/post" id="quoteform" encoding="multipart/form-data">
<input multiple type="file" name="files[]" id="quote" required />
<input type="submit" value="upload"/>
</form>
<script>
// html (xml) should mark the settings, behavior as it mostly always have done
// in all years way back and the js should provide enhancement and
// be more generally written to enhance the site (if js where
// to be turned off - most unlikely, I for once have it disabled in my phone)
// static sites works better without ads + annoying cookie popups
// it's a good thing Brave have quick toggle to enable scrips for js-only pages
function ajaxify (evt) {
evt.preventDefault()
var form = evt.target
var formData = new FormData(form)
fetch(form.action, {
method: form.method,
body: formData
}).then(res => res.text()).then(alert)
}
document.getElementById("quoteform").addEventListener("submit", ajaxify)
</script>

Why is $_FILES[] always empty?

The problem
I'm trying to make an AJAX file uploader with Php and Javascript. The problem I'm having is that in my upload.php script where I'm trying to use the move_uploaded_file function, the $_FILES array is always empty.
Here's what I've tried thus far
Checked file_uploads = On in /etc/php/7.2/apache2/php.ini
Checked the current working directory of uploader.php and upload.php
Checked the file permissions of uploads
Changed the uploads_tmp_dir in /etc/php/7.2/apache2/php.ini
The MWE
Html in uploader.php:
<form class="form" id="upload_form">
<input type="file" name="file_to_upload" id="file_to_upload"><br>
<input class="button" type="submit" value="Upload">
</form>
Javascript in uploader.php:
<script>
var upload_form = document.getElementById('upload_form');
var file_to_upload = document.getElementById('file_to_upload');
upload_form.addEventListener("submit", upload_file);
function upload_file (e) {
e.preventDefault();
var xhr = new XMLHttpRequest()
xhr.open("POST", "upload.php");
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.send(new FormData(upload_form));
}
</script>
upload.php:
<?php
//$target_path = "uploads/".basename($_FILES["file_to_upload"]["name"]);
$uploaded_file = $_FILES['file_to_upload']['tmp_name'];
var_dump($_FILES); // This is always array(0) { }
if(file_exists($uploadedFile)) {
echo "file uploaded to temp dir";
} else {
echo "file upload failed"; // This is always the outcome
}
//move_uploaded_file($_FILES["file_to_upload"]["tmp_name"], $target_path);
?>
According to the PHP docs, you must specify enctype="multipart/form-data". You must also specify method="post" -- see this answer for an explanation.
So your <form> should read:
<form class="form" id="upload_form" enctype="multipart/form-data" method="post">
In one of my projects using Framework-7. I was doing the same to get file upload form submission using ajax.
Do what #kmoser suggest in his answer but do as below as well.:)
<form class="form" id="upload_form" enctype="multipart/form-data" method="post">
<input class="button" type="submit" id="submission" value="Upload">
Now, my code:
$$('#submission').on('click', function(){
//alert('here');
//var test = $('#upload_form').serializeArray();
var fileInputElement = document.getElementById('file_to_upload');
var formData = new FormData();
formData.append('myfile', fileInputElement.files[0]);
var request = new XMLHttpRequest();
request.open("POST", "https://yourwebsite/upload.php");
request.send(formData);
//console.log(request.response);
request.onreadystatechange = function() {//Call a function when the state changes.
if(request.readyState == 4 && request.status == 200) {
alert("File has been uploaded successfully!");
//console.log('here');
location.reload();
}
}
});
and at last on upload.php file write below code:
if(isset($_FILES['myfile'])) {
//echo "uploaded something";
if($_FILES['myfile']['tmp_name'] != '') {
$tmp_filenm = $_FILES['myfile']['tmp_name'];
$file_name = time()."_".$_FILES['myfile']['name'];
$file_fullpath = $today_dir."/".$file_name;
//echo $file_fullpath;
move_uploaded_file("".$tmp_filenm,"$file_fullpath");
}
}

How to make my HTTP request behave the same as a form

I'd need some help with my HTTP request. Here's the setup:
A webpage load an image to a form and send it to a python server running bottle (with the form or a custom http request)
Bottle receive the file, give it as an input for a python script, receive the result and return it to the webpage
On bottle's website there's an example with a form: https://bottlepy.org/docs/dev/tutorial.html#file-uploads I've tried it and it works. Here's the code I used:
<html>
<head>
</head>
<body>
<form action="http://localhost:8080/solve" method="POST" enctype="multipart/form-data" norm="form" id='myForm'>
Select a file: <input type="file" name="upload"/>
<input type="submit" value="Start upload" />
</form>
</body>
</html>
In bottle I have:
#route('/solve', method='POST')
def solve():
file = request.files.get('upload')
name, ext = os.path.splitext(file.filename)
if ext not in ('.png','.jpg','.jpeg'):
return 'File extension not allowed.'
print(file.name)
resolved = sudoku.solve(file.file)
return str(resolved)
This "works", but the form redirects me to localhost:8080 and it's not what I want. I tried putting the target to a hidden iFrame, which prevent the redirection, but I don't manage to access the result in the body of the iFrame...
What I want: Make an HTTP request similar to the one made by the form. So I tried:
<html>
<head> </head>
<body>
<form enctype="multipart/form-data" norm="form" id="myForm">
Select a file:
<input id="fileInput" type="file" name="upload" accept="image/png, image/jpeg, image/jpg" />
<input type="submit" value="Start upload" />
<label class="button-upload" onclick="send()">Upload</label>
</form>
</body>
<script>
var _file = null;
function send() {
var file = document.getElementById("fileInput").files[0]
console.log(file)
var url = "http://localhost:8080/solve";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader(
"Content-Type",
"multipart/form-data; boundary=---------------------------169461201884497922237853436"
);
var formData = new FormData();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
formData.append("upload", file);
xhr.send(formData);
}
</script>
</html>
I've checked with the developper tool in network and the request seems to be the same as the one sent by the form, though bottle can't find the file.
The file = request.files.get('upload') returns None and file = request.files returns <bottle.FormsDict object at 0x7ff437abf400> so there's something but I don't understand how to access it!
Any help would be greatly appreciated!
Your JavaScript code seems fine, except for where you set request headers with xhr.setRequestHeader. FormData handles multipart encoding for you, you don't need to set request headers manually. I just tried it, and it seems to be working fine with bottlepy.
Overall, change your send() function as follows:
function send() {
var file = document.getElementById("fileInput").files[0]
console.log(file)
var url = "http://localhost:8080/solve";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
var formData = new FormData();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
formData.append("upload", file);
xhr.send(formData);
}

multipart/form-data possible to send with javascript?

I am sending a file over POST together with text "name" using this form:
<form enctype="multipart/form-data" action="https://site[DOT]net/upload" method="post">
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit" />
</form>
I would like to do the exect same using javascript. In addition I dont want to be redirected. I want to stay on the html page and just show a popup "Upload done". How can I do this in javascript (no jquery)?
EDIT:
I tried this code but the POST is not working:
<script>
function uploader {
var formData = new FormData();
formData.append("name", "Smith");
formData.append("data", fileInputElement.files[0]);
var request = new XMLHttpRequest();
request.open("POST", "https://site[DOT]net/upload");
request.send(formData);
}
</script>
<form>
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit" />
<button onclick="uploader()">Click</button>
</form>
In case any wants to do this with the new fetch instead of xhr this is the equivalent. Also see: How do I POST with multipart form data using fetch?
var form = document.getElementById('formid');
form.onsubmit = async (e) => {
e.preventDefault();
const form = e.currentTarget;
const url = form.action;
try {
const formData = new FormData(form);
const response = await fetch(url, {
method: 'POST',
body: formData
});
console.log(response);
} catch (error) {
console.error(error);
}
}
<form id="formid" enctype="multipart/form-data" action="#" method="post">
<input id="name" type="text" />
<input id="data" type="file" />
<button type="submit" name="submit">Submint</button>
</form>
Uploading the entire form with javascript, including the files, can be done by using the FormData API and XMLHttpRequest
var form = document.getElementById('myForm'); // give the form an ID
var xhr = new XMLHttpRequest(); // create XMLHttpRequest
var data = new FormData(form); // create formData object
xhr.onload = function() {
console.log(this.responseText); // whatever the server returns
}
xhr.open("post", form.action); // open connection
xhr.send(data); // send data
If you need to support IE10 and below, it gets increasingly complicated, and would in some cases require posting through iFrames etc.

How can I create and send a text file through XmlHttpRequest or $.ajax?

The server is expecting an html or txt file from a form with name: "websitetopdf". The file is created dynamically on client javascript and only have to work on Chrome.
This is the form that should be sending it:
<form action="send.php" method="post" enctype="multipart/form-data" name="websitetopdf" id="websitetopdf">
<input name="localfile" type="file" id="localfile" size="58">
<input name="filetype" type="hidden" id="filetype" value="IMG">
<input name="source" type="hidden" id="source" value="SOFT">
<input name="converternow" type="submit" id="converternow" style="width: 130px; font-weight: bold;" value="Convert to Image">
</form>
I want to directly send the file to send.php, I have tried this:
$("#sender").on("click", function(e) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://.../send.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) console.log(xhr.responseText);
};
xhr.onload = function(e) {
if (xhr.status == 200) console.log("uploaded"); //(correctly uploaded)
else console.log("Error " + e.status + " occurred uploading your file.<br \/>");
};
var blob = new Blob(['abc123'], {type: 'text/plain'});
var formData = new FormData();
formData.append("localfile", blob);
formData.append("filetype", "IMG");
formData.append("source", "SOFT");
xhr.send(formData);
});
I always get "it's not a valid file" from server
It started working when I added a filename for the blob in the FormData object:
formData.append("localfile", blob, "filename.txt");

Categories

Resources