The script is working fine, I'm using formData()for uploading the image with ajax, and it is correctly being uploaded to the folder, but I can't understand why my page is being refreshed after move_uploaded_file() gets called in the php script.
This is the full code:
index.html
<label>Add picture?</label>
<input type='file' accept='.png,.gif,.jpg' onchange='upload_img(this)'>
script.js
function upload_img(e) {
let file = e.files[0];
let formData = new FormData();
formData.append('file', file);
let xhr = new XMLHttpRequest();
xhr.onload = function () {
// I want to show a message here but the page is being refreshed
document.getElementById('ajax_result').innerHTML = xhr.responseText;
}
xhr.open("POST", "upload_img.php", true);
xhr.send(formData);
}
upload_img.php
<?php
if (!empty($_FILES['file'])) {
var_dump($_FILES['file']);
$path = "../img_uploads/";
$path = $path . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
echo "The file " . basename($_FILES['file']['name']) . " has been uploaded";
}
}
EDIT:
For testing purposes I deleted all forms in the page and the issue is still there.
Maybe try first xfr.open then xfr.onload
Related
I'm trying to send a file from a web page to a php script using FormData, and the file isn't showing up in the $_FILES variable in the PHP page. Not sure if my error is on the JS side or the PHP side, or if I'm misunderstanding something deeper about the process.
Here's my code:
function uploadFile() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log('success');
} else {
console.log('error');
}
}
};
xhr.open('POST','php/parsefile.php',true);
xhr.setRequestHeader("Content-Type","multipart/form-data");
var formData = new FormData();
formData.append("myfile", document.querySelector('#fileInput').files[0]);
xhr.send(formData);
}
<input type="file" id="fileInput">
<button onclick="uploadFile();">Upload</button>
Here's parsefile.php:
<?php
echo("Error: " . $_FILES["myfile"]['error'] . "\n");
echo("Name: " . $_FILES['file']['name'] . "\n");
When I upload a simple, small (64 bytes) text file, the console reads success, but the response from the server is just this:
Error:
Name:
What am I missing here? Thanks for any help anyone can provide.
I found two issues in your code:
In JavaScript code, you explicitly defined the "Content-Type" as "multipart/form-data". JS automatically gets the content type when you make the XHR Request.
In the 4th line of your PHP code, the key of the $_FILE is "file". You need to change it to "myfile", in order to make it work.
You can check my edited code below:
JS Code:
function uploadFile() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log('success');
} else {
console.log('error');
}
}
};
xhr.open('POST','php/parsefile.php',true);
var formData = new FormData();
formData.append("myfile", document.querySelector('#fileInput').files[0]);
xhr.send(formData);
}
PHP Code:
<?php
echo "Name: ". $_FILES['myfile']['name'];
echo "Error: ".$_FILES['myfile']['error'];
as mentioned in the title I am trying to pass pdf from backend php to frontend using jquery.
Sample php code.
public function printPdf(){
header('Content-Disposition: attachment; filename="kainos.pdf"');
$html = $this->request->post['pdf'];
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML('<div>Section 1 text</div>');
return $mpdf->Output();
}
function(response){
var blob=new Blob([response], { type: 'application/pdf' });
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="Kainos.pdf";
link.click();
}
What i get is empty pdf.
What i know :
Data is being transfered correctly, since plain html can be transfered and seen using javascript console.log
Pdf is being generated, since i can just move the contents of the function to other function and get the pdf in other page, but i don't need it there.
I suspect that pdf is getting destroyed while being transfered, but can't seem to find any information
on how to fix it. Any help is appreciated
EDIT
Problem was not in the method I am sending but in jquery, it handles blobs wierd, so I am in the middle of rewriting everything in vanila js.
var xhr = new XMLHttpRequest();
xhr.open('POST', document.location.origin + '/somelocation.php', true);
//Send data to server
xhr.send({$("#pdf").html()});
//Set response type to file
xhr.responseType = "blob";
//On response do...
xhr.onload = () => {
//Create file in client side from xhr response
var blob=new Blob([xhr.response], { type: 'application/pdf' });
//create clickable element to download file and click it.
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="kainos.pdf";
link.click();
}
});
Try sending some more headers with your php script (And modifying your current one):
public function printPdf(){
ob_clean();
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="kainos.pdf"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
$html = $this->request->post['pdf'];
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML('<div>Section 1 text</div>');
return $mpdf->Output();
}
I have a PHP code which produces a zip file and make it downloadable from browser. The download part looks like:
download.php
// force client download
if (headers_sent()) {
echo 'HTTP header already sent';
} else {
if (!is_file($zipFile)) {
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
echo $zipFile . ' not found';
} else if (!is_readable($zipFile)) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
echo $zipFile . ' not readable';
} else {
ob_start();
// http headers for zip downloads
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zipName . '"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
set_time_limit(0);
ob_flush();
ob_clean();
readfile($zipFile);
}
}
When called from the browser directly like localhost/download.php it works and makes me download the zipped file properly.
However, I need to call it from my JS web application.
The way I am invoking it is via a POST AJAX request that look like this:
var xhr;
if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); // all browsers
else xhr = new ActiveXObject("Microsoft.XMLHTTP"); // for IE
var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
if (xhr.readyState===4 && xhr.status===200) {
alert('Server reply: ' + xhr.responseText);
}
}
xhr.send(formData);
return false;
The code is triggered when I click on a button.
Apparently it's doing "something". The PHP intermediate outputs (some folders) are correctly created, but the download does not begin.
The alert('Server reply: ' + xhr.responseText); part shows a strange message with some messy symbols, which I guess derives from the files created and read as text somehow.
Here is a screenshot of the message:
The PHP script is sending the actual binary source of the zip file, while the AJAX request is trying to display it as text, that's the garbage you get.
If you really want to keep the AJAX (it would be more simple to just make a <form> that is sent to download.php), you could do one two things:
Just print the URL to $zipFile in PHP, and then when you get the response redirect to it with window.location.href=xhr.responseText;.
Save the response as a zip file. See How to save binary data of zip file in Javascript?
After following option 2 in #Gabriel accepted answer I was able to make my code working. Here is the modified version of the JS (I didn't make any change in the PHP code):
var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
if (xhr.readyState===4 && xhr.status===200) {
var blob = new Blob([xhr.response], { // SOLUTION
type: "application/zip", // SOLUTION
}); // SOLUTION
var filename = "test.zip"; // SOLUTION
if (navigator.msSaveOrOpenBlob) { // SOLUTION
navigator.msSaveOrOpenBlob(blob, filename); // SOLUTION
} else { // SOLUTION
var a = document.createElement("a"); // SOLUTION
document.body.appendChild(a); // SOLUTION
a.style = "display:none"; // SOLUTION
var url = window.URL.createObjectURL(blob); // SOLUTION
a.href = url; // SOLUTION
a.download = filename; // SOLUTION
a.click(); // SOLUTION
window.URL.revokeObjectURL(url); // SOLUTION
a.remove(); // SOLUTION
} // SOLUTION
}
}
xhr.responseType = "arraybuffer"; // SOLUTION
xhr.send(formData);
I am curious about implementing one feature into my small project.
Basically, what I want is when I go to one specific page, I want to start recording video and audio with my webcam, and save that session in my Apache server. Now, the thing is that I want to stream that as a data, and not record it and then send that file to a server. The reason for that is because when I am done with that page, I will be transferred to a different page and I will not have time to do upload the whole video.
I have found this on one git page,
<?php
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
echo 'uploads/';
$fileName = $_POST["${type}-filename"];
$uploadDirectory = 'uploads/'.$fileName;
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo(" problem moving uploaded file");
}
echo($fileName);
}
}
?>
And Javascript
var fileType = 'video'; // or "audio"
var fileName = 'ABCDEF.webm'; // or "wav"
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
xhr('save.php', formData, function (fName) {
window.open(location.href + fName);
});
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(location.href + request.responseText);
}
};
request.open('POST', url);
request.send(data);
}
but I am not sure if that is the streaming solution (as I mentioned), and not record and then upload.
I am using PHP with some Javascript and have Apache as a server.
I want to make image upload from url for example: http://.. ../logo.png
I need to make formData object from image url but it doesn't work:
HTML:
<form id="form-url">
<input type="text" class="image" id="textarea" placeholder="URL" />
<button>UPLOAD</button>
</form>
Javascript:
$("#form-url").submit(function(e) {
if ($(".image").val() != "URL" && $(".image").val() != "") {
//I also tried this:
var data;
var img = new Image();
img.src = $(".image").val();
img.load = function(){
data = getBase64Image($(".image").val());
};
//but it send undefined
//and this:
var data = URL.createObjectURL($(".image").val()); //dont work
//error: TypeError: Argument 1 is not valid for any of the 1-argument overloads of URL.createObjectURL.
//Upload process working on normal input type file uploading but no on URL image
var formData = new FormData(data);
formData.append("fileToUpload", data);
var xhr = new XMLHttpRequest();
xhr.open('POST', "upload_ajax.php", true);
xhr.onload = function () {
if (xhr.status === 200) {
data = xhr.responseText;
datas = data.split("_");
if (datas[0] != "true") {
alert(data);
} else {
alert('YES');
}
} else {
alerter('An error occurred while uploading this file! Try it again.');
}
};
xhr.send(formData);
} else { alerter("Your file must be an image!"); }
return false;
});
My php script for debug:
<?php
if (isset($_POST)) {
var_dump($_POST);
if (empty($_FILES['fileToUpload']['tmp_name'])) {
echo "Your file must be an image!";
} else {
echo $_FILES['fileToUpload']['name'];
echo $_FILES['fileToUpload']['size'];
}
}
?>
Thanks for all help and your time..
and sorry for my bad english (student)
If getBase64Image is from here, or is similar to it.
Then you are using it wrong. You need to pass it the image node itself. Also the image onload event is async, and as such you have to wait for it to be done to get the data and send it.
var xhr = new XMLHttpRequest();
var formData = new FormData();
xhr.open('POST', "upload_ajax.php", true);
...
var img = new Image();
img.onload = function(){
var data = getBase64Image(this);
formData.append("fileToUpload", data);
xhr.send(formData);
};
Also note on the server side you will need to decode it from the base64 encoding, as it is being sent by string, it is going to be in $_POST not $_FILE
var rawContents = base64_decode($_POST['fileToUpload']);
Note you could also just send the url to the php script and just have php get the image data
var rawContents = file_get_contents($_POST['imageurl']);