Uploading file and $_POST with AJAX fails - javascript

I'm trying to upload a file and some text inside a textarea together using AJAX. I'm getting the following error in the PHP page that receives the data:
Notice: Undefined index: guion in file/path/here on line X
It means that the file is not being sent. Tried var_dump $_FILES and it output:
array(0) { }
HTML Code:
<div id="_AJAX_"></div>
<div role="form">
<div id="fileGuionGroup" class="form-group">
<label for="guion">Archivo Guión</label>
<input id="fileGuion" type="file" name="guion">
</div>
<div id="txtComentarioGroup" class="form-group">
<label for="comentario">Comentario</label>
<textarea id="txtComentario" class="form-control" name="comentario" rows="4" placeholder="Ejemplo: Solicito que por favor se monte este curso en plataforma."></textarea>
</div>
</div>
<button id="send_request" type="button" class="btn btn-primary btn-block" onclick="submitSolicitud(`{$cursoKey}`)"><i class="fa fa-fw fa-cogs"></i> Solicitar Montaje</button>
Javascript Code:
function submitSolicitud(cursoKey) {
var fileGuion = document.getElementById('fileGuion');
var txtComentario = document.getElementById('txtComentario');
var formGroupGuion = document.getElementById('fileGuionGroup');
var formGroupComentario = document.getElementById('txtComentarioGroup');
formGroupGuion.className = "form-group";
formGroupComentario.className = "form-group";
var guion = fileGuion.value;
var comentario = txtComentario.value;
var formData = new FormData();
formData.append('guion', guion);
formData.append('comentario', comentario);
connect = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
connect.onreadystatechange = function () {
onRSCallback(cursoKey);
};
connect.open('POST', '?view=modalsMatriz&modal=montaje&id=' + cursoKey + '&action=solicitarMontaje', true);
connect.setRequestHeader("Content-Type", "multipart/form-data");
connect.setRequestHeader("X-File-Name", guion.name);
connect.setRequestHeader("X-File-Size", guion.size);
connect.setRequestHeader("X-File-Type", guion.type);
connect.send(formData);
};
PHP Code:
case 'solicitarMontaje':
// This is the line that has the error of undefined index.
die($_FILES['guion']);
try {
if (!isset($_FILES['guion'])) {
# Code 1: Archivo Guión Field vacía
throw new Exception(1);
} elseif (!isset($_POST['comentario']) || $_POST['comentario'] == "") {
# Code 2: Comentario Field vacío
throw new Exception(2);
}
$tmp_file = $_FILES['guion']['tmp_name'];
$filename = $_FILES['guion']['name'];
move_uploaded_file($tmp_file, 'uploads/guiones/'.$filename);
die(0);
//$curso->crearSolicitudMontaje($_POST['comentario']);
} catch (Exception $e) {
# Output message to the screen so that Ajax captures it via connect.responseText #curso_FormMontaje.js
echo $e->getMessage();
}
break; # ./ case 'solicitarMontaje'
I've tried it using FormData() and Content-Type multipart/form-data but it did not work at all. Instead it was making the page be embedded inside the _AJAX_ div that shows the messages returned from the server (such as success messages, errors at some fields i.e fields that were sent empty).
This is what I get as result using FormData when clicking the submit button:
https://postimg.org/image/rsnrt3yq9/

Here is a very simple form data example, given what you have provided:
<script>
$(document).ready(function(){
// I don't know what your form is called...
$('.uploader').submit(function(e) {
// Clone the file input
var getFileInput = $("#fileGuion").clone();
// Stop form from submitting
e.preventDefault();
$.ajax({
url:'/url/to/ajax/dispatcher.php',
// Use FormData object, pass form
data: new FormData($(this)[0]),
processData: false,
contentType: false,
type: 'post',
success: function(response) {
// Put html back into placeholder
$('#_AJAX_').html(response);
// Replace the input
$("#fileGuion").replaceWith(getFileInput);
}
});
});
});
</script>
<div id="_AJAX_"></div>
<form class="uploader">
<label for="guion">Archivo Guión</label>
<input id="fileGuion" type="file" name="guion">
<label for="comentario">Comentario</label>
<textarea id="txtComentario" class="form-control" name="comentario" rows="4" placeholder="Ejemplo: Solicito que por favor se monte este curso en plataforma."></textarea>
<label>
<input type="checkbox" id="ackCheckbox"> <i>He revisado y estoy seguro de continuar con esta acción.</i>
</label>
<input type="submit" value="Upload">
</form>

Turns out that what was causing issues were the HTTP headers (setRequestHeader). I removed them and edited the code a little bit, here's what it looks like now fully functional:
JavaScript Code:
function submitSolicitud(cursoKey) {
var fileGuion = document.getElementById('fileGuion');
var txtComentario = document.getElementById('txtComentario');
var guion = fileGuion.files[0];
var comentario = txtComentario.value;
var formData = new FormData();
formData.append('guion', guion);
formData.append('comentario', comentario);
connect = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
connect.onreadystatechange = function () {
onRSCallback(cursoKey);
};
connect.open('POST', '?view=modalsMatriz&modal=montaje&id=' + cursoKey + '&action=solicitarMontaje', true);
connect.send(formData);
};
As expected, the data is recognized by PHP as below:
The file "guion" comes into PHP's $_FILES array ($_FILES['guion']).
The "comentario" field (textarea) is sent inside PHP's $_POST array ($_POST['comentario']).
Finally, both HTML and PHP code stayed the same and the conclusion is that by not setting the HTTP headers they seem to take the proper value automatically so that the request processes correctly.

Related

$_FILES not receiving input after AJAX with vanilla Javascript

I have a form that passes various types of input to an ajax call, which opens a php script. The script will do various things including processing the file, before echoing an array of variables.
All inputs go through $_POST regularly, and the file data is passed, too, but the file itself is not accessible from $_FILES.
I am not using jQuery, so most posts are hard to translate to my case.
I have seen a similar issue here,https://stackoverflow.com/questions/56878395/files-empty-after-ajax-upload but that solution doesn't seem to apply.
Here are the key excerpts from the code, thank you in advance for any tips!
var ajaxResponse = "";
var qForm = document.getElementById('myForm');
qForm.addEventListener("submit", function(e) {
e.preventDefault();
var formData = new FormData(qForm);
checkForm(formData);
console.log(ajaxResponse); //this shows the $_FILES var_dump
});
function checkForm(formData) {
var vars = "startDate=" + formData.get('startDate') +
"&qInvited=" + formData.get('qInvited');
ajaxRequestReturn("checkForm.php", vars);
}
function ajaxRequestReturn(phpRequest, vars) {
var req = new XMLHttpRequest();
req.open("POST", phpRequest, false); //not asynchronous, because I pass results to a global variable
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //removing the setRequestHeader doesn't seem to make any difference.
req.onload = function() {
ajaxResponse = this.responseText;
}
req.onerror = function() {
throw new Error("Bad request.");
}
req.send(vars);
// form.submit();
}
<form class="loginForm" id="myForm" method="post" enctype="multipart/form-data" action="thisPage.php">
<div>
<input type="date" id="startDateInput" name="startDate">
</div>
<div>
<input type="file" name="qInvited" required>
</div>
<input type="submit" id="submitBtn">
</form>
and the checkForm.php file is currently simply:
<?php
echo var_dump($_FILES);
?>
the var_dump($_FILES) should show the qInvited file in it, but it prints
array(0) {
}
instead.
To upload a file via ajax you have to pass a FormData object in your call to XMLHttpRequest.send.
Get rid of the checkForm function and call ajaxRequestReturn with formData as the second parameter.
Also, application/x-www-form-urlencoded is not the correct content type(its multipart/form-data), remove that line. The correct content type will be set automatically when you use the FormData object.

How do I get and print a variable stored in localStorage with a POST request?

In an application in Flask, I need to take a user data from a form to store it with the "localStorage" function and print it on a new page after a POST request allowing to keep the printed name even if the page restarts. I have this code:
index.html:
<body>
<form id="registro" action="{{ url_for('chatroom') }}" method="post">
Ingresa al chat <br/>
<p><input type="text" id="usuario" name="usuario" placeholder="Usuario">
</p>
<input type="submit" id="guardar" value="Enviar" /><br>
</form>
</body>
Function in Python/Flask:
#app.route("/chatroom", methods=["POST"])
def chatroom():
Usuario = request.form.get("usuario")
return render_template("chatroom3A.html", Usuario=Usuario)
chatroom3A.html
<body>
…………………………..
<div>Bienvenid# <label type="text" id="bienvenido"></label></div>
…………………………….
</body>
Code in Javascript:
if (localStorage.getItem('userlog')) {
const TheUserlog = localStorage.getItem('userlog');
}
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#registro').onsubmit = () => {
// Initialize new request
const request = new XMLHttpRequest();
const nombre = document.querySelector('#usuario').value;
localStorage.setItem("userlog", nombre);
document.getElementById("usuario").value = "";
request.open('POST', '/chatroom');
const data = new FormData();
data.append('usuario', usuario);
// Send request
request.send(data);
// Callback function for when request completes
request.onload = () => {
const TheUserlog = localStorage.getItem('userlog');
if (request.status == 200) {
document.querySelector('#bienvenido').innerHTML = TheUserlog;
}
}
};
});
when chatroom3A.html is rendered, the page does not print the data ("usuario") from the form into index.html. I do not know how to indicate the contents to print with "innerHTML", perhaps with the function "responseText". I hope you can help me.

Post data info to CGI script using javascript

I have this very simple HTML Form. I want to pass the input to a CGI script (Python), which will store them into mysql table.
<!DOCTYPE html>
<html>
<body>
<h2>Cadastro</h2>
<form name="cadastro" id="cadastro" action="/cgi-bin/cadastro.py" method="POST">
<label for="nome">Nome completo:</label><br>
<input type="text" id="nome" name="nome" required><br>
<label for="mae">Nome completo da mãe:</label><br>
<input type="text" id="mae" name="mae" required><br>
<br><br>
<input type="submit">
</form>
</body>
</html>
The form works great and data is correctly stored into the mysql table.
However, I wanted to make a "successful" message when clicking the submit button, instead of redirecting it to the cgi script.
I believe the easiest way to do that is using javascript. Then, I tried adding this to the code:
<script>
const cadastro = document.getElementById("cadastro");
cadastro.addEventListener("submit", (e) => {
e.preventDefault();
const request = new XMLHttpRequest();
request.open("post", "/cgi-bin/cadastro.py")
request.send();
});
</script>
Here is the python script, in case its necessary:
print("Content-type: text/html\r\n\r\n")
import cgi, mysql.connector
db = mysql.connector.connect(
host = "xxx",
user = "yyy",
password = "aaa",
database = "bbb",
)
cadastro = cgi.FieldStorage()
def add_cliente(nome, mae):
cursor = db.cursor()
cursor.execute("INSERT INTO cadastro (nome, mae) VALUE (%s, %s)", (nome, mae))
db.commit()
return print(cursor.rowcount, "record inserted.")
add_cliente(cadastro.getvalue("nome"), cadastro.getvalue("mae"))
However, the user input is stored as NULL in the mysql table. Could someone help, please?
It comes down to the script not sending any data, thus the NULL values. As mentioned, the cgi script was working good.
Here is an example javascript code, extracted from here:
window.addEventListener( "load", function () {
function sendData() {
const XHR = new XMLHttpRequest();
// Bind the FormData object and the form element
const FD = new FormData( form );
// Define what happens on successful data submission
XHR.addEventListener( "load", function(event) {
alert( event.target.responseText );
} );
// Define what happens in case of error
XHR.addEventListener( "error", function( event ) {
alert( 'Oops! Something went wrong.' );
} );
// Set up our request
XHR.open( "POST", "https://example.com/cors.php" );
// The data sent is what the user provided in the form
XHR.send( FD );
}
// Access the form element...
const form = document.getElementById( "myForm" );
// ...and take over its submit event.
form.addEventListener( "submit", function ( event ) {
event.preventDefault();
sendData();
} );
} );

When one div loads, the other div is deleted

Click here: henriquecosta.kdhost.eu.org, type the number 00008513 and choose a radio button and enter, then choose any 8-digit number and type. This part is working wonderfully after so much sacrifice for me, I'm not a programmer. The problem is that when another div is loaded, the previous one is deleted. I need all divs to remain on the page, in all it will be 40 divs. Yesterday I could not resolve with the localstorage, I think it is the solution, after that the script will be finished. Well, I'm happy with what I got so far. If anyone has any tips to give me, I'll be very grateful! Thank you.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
</head>
<body>
<script>
var form = document.querySelector('form');
form.addEventListener('submit', function(e) {
e.preventDefault(); // <--- isto pára o envio da form
var url = this.action; // <--- o url que processa a form
var formData = new FormData(this); // <--- os dados da form
var ajax = new XMLHttpRequest();
ajax.open("GET", url, true);
ajax.onload = function() {
if (ajax.status == 200) {
var dados = JSON.parse(ajax.responseText);
alert('Dados enviados:\n' + JSON.stringify(dados, null, 4));
} else {
alert('Algo falhou...');
}
};
ajax.send(formData);
});
</script>
<form action="index.php">
Cartao:<input size="7" name="cartao" value="" required="" pattern="[0-9]{8}" type="text">
<input value="01" name="armario" type="radio" />01
<input value="02" name="armario" type="radio" />02
<input value="03" name="armario" type="radio" />03
<button type="submit">Enviar</button>
</form>
<table width=100% border=1>
<tbody>
<tr align=center valign="middle">
<td width=33%><div id="01"></div></td>
<td width=33%><div id="02"></div></td>
<td width=33%><div id="03"></div></td>
</tr>
</tbody>
</table>
<?php
if (isset($_GET['cartao'])):
$radioValue = $_GET['armario'];
$radiovalor = '"'.$radioValue.'"';
$file = 'banco.txt';
$searchfor = $_GET['cartao'];
//header('Content-Type: text/plain');
$contents = file_get_contents($file);
$pattern = preg_quote($searchfor, '/');
$pattern = "/^.*$pattern.*\$/m";
if(preg_match_all($pattern, $contents, $matches)):
json_encode($matches[0]);
$resultado = str_replace(array('"',' \r','[', ']'), '', htmlspecialchars(json_encode($matches[0]), ENT_NOQUOTES));
else:
$resultado = $_GET['cartao'];
endif;
else:
echo '';
endif;
// file_exists
if (isset($_GET['cartao'])) {
$path = './fotos/';
$recebe = $_GET['cartao'];
$img = $path.$recebe.".jpg";
if (file_exists($img)) {
$foto = '"<img width=80 height=80 src="'.$img.'">'; // existe
} else { $foto = ' <img width=80 height=80 src="./fotos/ausente.jpg">'; // não existe
}
}
?>
<script>
var x = '<?php echo $resultado, $foto; ?>';
var z = '<?php echo $radioValue; ?>';
document.getElementById(z).innerHTML += x;
</script>
</body>
</html>
There are several problems in your code which you are probably not aware of.
First of all, your whole page is reloaded everytime you click the "Enviar" button, because your javascript does not correctly prevent the default action.
To accomplish this, return false at the end of the function:
var form = document.querySelector('form');
form.addEventListener('submit', function(e) {
e.preventDefault(); // <--- isto pára o envio da form
var url = this.action; // <--- o url que processa a form
var formData = new FormData(this); // <--- os dados da form
var ajax = new XMLHttpRequest();
ajax.open("POST", url, true);
ajax.onload = function() {
if (ajax.status == 200) {
var dados = JSON.parse(ajax.responseText);
alert('Dados enviados:\n' + JSON.stringify(dados, null, 4));
} else {
alert('Algo falhou...');
}
};
ajax.send(formData);
return false;
});
By doing this, the whole page will not be reloaded.
Secondly, your server always returns a full html page, instead of differentiating, whether the url has been accessed by opening the page for the first time or if it received a request from your script.
If isset($_POST['cartao'] is true, than the request came from your javascript and you should return a JSON object containing the relevant data and build the html in your javascript and append it to your table.
I know that this all sounds a bit confusing if you are not a programmer but I hope I could point you in the right direction.
Once you return a JSON object from your server, I am happy to help you to render HTML from it in javascript.

Javascript to send form to PHP

I am trying to get my HTML form to pass through Javascript that will then pass it to PHP that will send it to MySQL.
However I either get the page to load the JS file in the browser, or the PHP file to load in the browser.
Here is my HTML form:
<div class="form" id="form" onclick="submitForm()">
<form id='contactform' action="js/contactform.js" method="post" onSubmit="submitForm()">
<input type="text" id="name" placeholder="Name" autofocus required><br>
<input type="text" id="email" placeholder="Email" required><br>
<input type="tel" id="telephone" placeholder="Telephone"><br>
Enquiry : <input type="radio" id="subject" value="enquiry" required>
Booking : <input type="radio" id="subject" value="booking" required><br>
<textarea id="message" required rows="20" cols="20" placeholder="Enter your message and I will try to get back to you within 2 days."></textarea><br>
<input type="submit" name="submit" value="Submit" class="submitbutton"/>
<input type="reset" name="clearbutton" value="Clear" class="clearbutton"/>
</form>
<div id="outcome"></div>
I want the outcome of the form submit placed into the "outcome" div
My JS code:
function getOutput() {
getRequest(
'php/getinfo.php',
drawOutput,
drawError
);
return false;
}
// handles drawing an error message
function drawError () {
var container = document.getElementById("content");
container.innerHTML = 'Bummer: there was an error!';
}
// handles the response, adds the html
function drawOutput(responseText) {
var container = document.getElementById("content");
container.innerHTML = responseText;
}
// helper function for cross-browser request object
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req .readyState == 4){
return req.status === 200 ?
success(req.responseText) : error(req.status)
;
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
function submitForm(){
var name = document.getElementById('name').value;
var booking = document.getElementById('subject').value;
var enquiry = document.getElementById('subject').value;
var email = document.getElementById('email').value;
var telephone = document.getElementById('telephone').value;
var message = document.getElementById('message').value;
getRequest(
'php/form.php?' + params, //URL for the PHP file
procesOutput,
processError
);
return false;
}
function processOutput(){
var container = document.getElementById('outcome');
container.innerHTML = responseText;
}
function processError(){
alert("There has been an error, please try again");
}
and my PHP code:
$con=mysqli_connect("DBLocation","Username","Password",'DBName');
if (mysqli_connect_errno()){
die("Error: " . mysqli_connect_error());
}
$result = mysqli_query($con,"INSERT INTO `Contact`(`Name`, `Email`, `Telephone`, `Enquiry`, `Booking`, `Message`) VALUES ([value-2],[value-3],[value-4],[value-5],[value-6],[value-7])");
if ($conn->query($sql) === TRUE){
echo "Thank you for contacting us, I will replay to you soon!";
}
else {
echo "I'm sorry but an Error has occured. Please try again shortly";
}
mysql_close($conn);
?>
I've had a look at w3schools pages and some other questions on here but I can't seem to get my head around it.
A couple of things, first off what is getRequest? Second off, where is responseText defined? Third, I would check your console as I'm pretty sure there is an error in submitForm. I see lots of getElementByIds, but none of your inputs have ids associated with them:
<input type="text" name="name" placeholder="Name" autofocus required>
Should be:
<input type="text" id="name" placeholder="Name" autofocus required>
I believe you want to use Ajax, which you can easily use with jQuery.
I believe the answer for your question is right on this page: https://learn.jquery.com/ajax/ajax-and-forms/
If jQuery is new for you, you might want to read a little about jQuery: https://learn.jquery.com/about-jquery/
If you don't want to use jQuery, you can use directly XMLHttpRequest in javascript instead.
Here is a demo in JSFiddle.
Remove onClick, onSubmit, action="js/contactform.js" method="post" attributes as you don't need them. Capture the form submit in js. How to? - link
Add id's on the form elements so than you can select them like:
var name = document.getElementById('name').value;
Make a $.post request with jQuery (How to? - Link) and handle the success and failure callbacks. (I don't understand why are you making a post request, I would recommend you a $.get request.

Categories