I have been trying to upload an image to my server from jQuery to PHP, but the uploaded content is always invalid image. I could not identify the error whether I was encoding or decoding it wrong. How can I fix this?
jQuery code
$("input[type=file]").change(function(event) {
$.each(event.target.files, function(index, file) {
var reader = new FileReader();
reader.onload = function(event) {
var object = {};
object.filename = document.querySelector('input[type=file]').files[0]['name'];;
object.data = encodeURI(event.target.result);
object.filetype = document.querySelector('input[type=file]').files[0]['type'];
files.push(object);
};
reader.readAsDataURL(file);
});
});
$("form").submit(function(form) {
$.each(files, function(index, file) {
$.ajax({url: "handle.php",
type: 'POST',
data: {fileName: file.filename, data: file.data, fileType: file.filetype},
success: function(data) {
$('#data').html(data);
}
});
});
files = [];
form.preventDefault();
});
PHP code
if (isset($_POST["data"]) || isset($_POST["fileName"])) {
$data = $_POST["data"];
$fileName = $_POST["fileName"];
$fileType = $_POST["filetype"];
$replace = "data:" . $fileType . ";base64,";
$filedata = str_replace($replace, "", $data); // echo $filedata;
$decodedData = urldecode($filedata); // echo $decodedData;
$fp = fopen('uploads/' . $fileName, "w");
fwrite($fp, $decodedData);
fclose($fp);
}
First make sure you get the Base64 code on the server. For example, you can echo, etc.
Then assuming your image Base64 code was in $_POST['image']:
$data = $_POST['image']
$data = str_replace('data:image/png;base64,', '', $data);
$data = base64_decode($data); // Base64 decoded image data
$source_img = imagecreatefromstring($data);
$imageSave = imagejpeg($source_img, $file, 10);
imagedestroy($source_img);
Using the above lines you can save the image as a file from Base64.
In jQuery do it this way:
$.each(event.target.files, function(index, file) {
var FR = new FileReader();
FR.onload = function(e) {
object.data = e.target.result; };
FR.readAsDataURL(this.files[0]);
}
FR.readAsDataURL(file);
}
What I see is the you are encoding it wrongly in this line
object.data = encodeURI(event.target.result);
A few small mistakes, otherwise it's almost working.
In reader.onload you are using document.querySelector('input[type=file]').files[0]['name']; which would select only the first file (see the constant files[0]). So instead of manually searching you can use file parameter of each loop to get filename and type:
var files = [];
$("input[type=file]").change(function(event) {
$.each(event.target.files, function(index, file) {
var reader = new FileReader();
reader.onload = function(event) {
var object = {};
object.filename = file.name;
object.data = encodeURI(event.target.result);
object.filetype = file.type;
files.push(object);
};
reader.readAsDataURL(file);
});
});
In PHP code, a small mistake:
$fileType = $_POST["filetype"]; // <-- small "t"
urldecode cannot decode Base64. For that, use base64_decode:
$decodedData = base64_decode($filedata); // echo $decodedData;
Related
I create a PHP and ajax codes to create CSV file and download it when click a button. The PHP codes work fine, and for ajax I modify and set js codes according to Handle file download from ajax post all works good. but the downloaded csv file is empty while the file in custom file is correct. I use this codes in custom wordpress plugin.
function _exe_export_vendor_products(){
$current_user_id = esc_sql($_POST['c_user_id']);
$arg = array(
'limit' => 20,
'author' => $current_user_id
);
$product_list = wc_get_products($arg);
$title_array[] = array('ID', 'name', 'Price', 'SalePrice');
foreach($product_list as $_list){
$data_array[] = array($_list->get_id(), $_list->get_name(), $_list->get_price(), $_list->get_sale_price());
}
$final_array = array_merge($title_array, $data_array);
date_default_timezone_set("Asia/Tehran");
$current_date = date('Y-m-d-H-i');
$filename = "export-" . $current_user_id . "-" . $current_date . ".csv";
$f = fopen('https://sitename.com/export-import/' . $filename, 'w');
$delimiter=";";
foreach($final_array as $final_item){
fputcsv($f, $final_item, $delimiter);
}
fseek($f, 0);
header('Content-Type: text/csv; charset=UTF-8' );
header('Content-Encoding: UTF-8');
header('Content-Disposition: attachment; filename="'.$filename.'";');
readfile($filename);
fclose($f);
}
and JS codes:
jQuery.ajax({
type: "POST",
url: Ajax_object_dokan.ajax_url,
data:{
action: '_dokan_export_vendor',
c_user_id : current_user_id
},
xhrFields:{
responseType: 'blob'
},
success: function(blob, status, xhr){
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if(disposition && disposition.indexOf('attachment') !== -1){
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
I create file in https://sitename.com/export-import/filename.csv while the create tag a in JS has link to https://sitename.com/59360c8b-22a5-462b-9d7e-240e54a0c094.
How can I access to correct link to download file with ajax?
There are several issues in your code:
You use fopen() to access a URL with w mode. It can't work. You can only access a URL for reading.
Just use a path on the filesystem, for example:
$f = fopen($_SERVER['DOCUMENT_ROOT'] . '/export-import/' . $filename, 'w');
You call readfile() with just the file name, not the full path.
You call readfile() on the file before closing it. It may work but it's better to call fclose() first.
And you don't need to call fseek().
You set the Content-Encoding: UTF-8 header. That header is used to indicate compression (e.g. gzip), not
the character encoding. Remove it.
Also note that you don't need AJAX to download a file. You can just submit a form. All that complicated JS code is unnecessary.
I have a file type input. I want the photo that is inserted in the input to be sent to the db and saved. I wrote some code that according to logic should work. but I do not know why it does not work. where am I wrong? the column photo is a longblob type
html
<label for="">img</label>
<input type="file" id="immagine" >
javascript
function values(a){
if (a.length>1){
var img;
const fr = new FileReader();
fr.onload = () => {
// It worked
img = fr.result;
var params= "V1="+a[2]+"& V2="+a[3]+"& V3="+a[4]+"& V4="+a[5]+"& V5="+a[6]+"& V6="+a[7]+"& V7="+a[8]+"& V8="+a[9]+"& V9="+a[10]+"& V10="+a[11]+"& V11="+a[12]+"& V12="+a[13]+"& V13="+a[14]+"& V14="+a[15]+"& img="+img;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
}
};
xhttp.open("POST", "./server/AggiuntaBhk.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send( params);
// ...use the array here...
};
fr.onerror = () => {
// The read failed, handle/report it
document.getElementById("a").innerHTML= "noo";
};
fr.readAsBinaryString(document.getElementById('immagine').files[0]);
}
}
php
include("../../connessione_db/db_con.php"); // Include il file di connessione al database
session_start();
$v1=$_REQUEST["V1"];
$v2=$_REQUEST["V2"];
$v3=$_REQUEST["V3"];
$v4=$_REQUEST["V4"];
$v5=$_REQUEST["V5"];
$v6=$_REQUEST["V6"];
$v7=$_REQUEST["V7"];
$v8=$_REQUEST["V8"];
$v9=$_REQUEST["V9"];
$v10=$_REQUEST["V10"];
$v11=$_REQUEST["V11"];
$v12=$_REQUEST["V12"];
$v13=$_REQUEST["V13"];
$v14=$_REQUEST["V14"];
$foto=$_REQUEST["img"];
$queryInput="INSERT INTO bhk (Metrica1,Metrica2,Metrica3,Metrica4,Metrica5,Metrica6,Metrica7,Metrica8,Metrica9,Metrica10,Metrica11,Metrica12,Metrica13,Data,Puntoz,Paziente,Foto) VALUES ('$v1','$v2','$v3','$v4','$v5','$v6','$v7','$v8','$v9','$v10','$v11','$v12','$v13','2014-01-01','$v14','BVNVCN97L18C983O','$foto')";
$queryI = mysqli_query($connessione_al_server,$queryInput);
after query to display
<?php
echo '<img id="imgcaricata" class="mySlides"
src="data:image/jpeg;base64,'.base64_encode( $foto["Foto"]
).'"
style="height:auto; width:auto;max-width:500px; margin-top:55px;" />';
?>
I also tried with until8Array and FileReader.readAsArrayBuffer() in the db I have the correct file but does not display anything. I can only see the image if I insert the image directly in the db using the browse option. am I wrong to store or display?
First read file by JavaScript:
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("immagine").files[0]);
oFReader.onload = function (oFREvent) {
imgdata = oFREvent.target.result;
};
Add imgdata in params:
var params = "img=" + encodeURIComponent(imgdata);
Send it to server:
xhttp.send(params);
After query to display:
<?php
echo '<img id="imgcaricata" class="mySlides" src="'.$foto["Foto"].'" style="height:auto; width:auto;max-width:500px; margin-top:55px;"/>';
?>
I'm trying to send an image from user's computer using an input (file).
I resize the image using a canvas and then get a base64 string encoded via the toDataURL method of the canvas.
Then I send the encoded string to my server via an AJAX request. In PHP, I receive properly the POST data, but it fails when I want to use the base64_decode to save the encoded string into a file on my server.
CLIENT SIDE :
function upload_document(file){
var url_post_document = "url_to_server";
var type_img = file.type;
var reader = new FileReader();
reader.onload = function(evt){
var image = document.createElement('img');
image.onload = function (){
var canvas = document.createElement('canvas');
canvas.height = 40;
canvas.width = 40;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, 40, 40);
var shrinked = canvas.toDataURL(file.type);
//console.log(shrinked);
$.ajax({
url: url_post_document,
type: 'POST',
xhrFields: {
withCredentials: false
},
data: {
"user_id": user_id,
"image": shrinked,
"image_type": type_img
},
success: function(data) {
console.log("RESPONSE");
console.log(data);
},
error: function() {
console.log("----- FAIL -----");
},
complete: function() {
console.log("----- REQUEST COMPLETED -----");
}
});
};
image.src = reader.result;
};
reader.readAsDataURL(file);
}
SERVER SIDE :
if(isset($_POST['user_id'])){
$extension = explode('/', $_POST['image_type']);
$extension = $extension[1];
define('UPLOAD_DIR', WP_CONTENT_DIR.'/uploads/userthumb/');
$imgBaseData = rtrim($_POST['image']);
$img = str_replace('data:'.$_POST['image_type'].';base64,', '', $imgBaseData);
$img = str_replace(' ', '+', $img);
$baseimage = base64_decode($img, true);
return $baseimage;
}
I tried to copy and past the base64 string got from the toDataURL method on an online base64decoder and it works, the image is displayed. But on the server, impossible to decode the string.
I would appreciate any help on this matter. Thanks in advance !
I have this in my html page:
<input type="file" id="fileInput" />
and this in my javascript page:
window.onload = function () {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function (e) {
// code that handles reading the text file
var file = fileInput.files[0];
var textType = /text.*/;
// checks if the file is a text file
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function (e) {
fileDisplayArea.innerText = reader.result;
}
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!";
}
});
}
I want to be able to convert the Filereader into an array so I can do something like:
document.getElementById("today").innerHTML = today[0];
Is this possible? I also don't think this is the way to read a csv file using filereader.
UPDATE: I have figured out how to get the csv file and turn it into an array by the following code:
$(document).ready(function () {
$.ajax({
type: "GET",
url: "data.csv",
dataType: "text",
success: function (data) { processData(data); }
});
function processData(csv) {
var temp = new Array();
temp = csv.split(",");
document.getElementById("today").innerHTML = temp[0];
}
});
Now I am wondering if there is a way to use FileReader() so I can select the file from the html page instead of using url: "data.csv" so I can select multiple files.
You can handle this a few ways. You might think to ajax the file to a PHP script, then do something like $csvData[] = fgetcsv($file). Then you can echo json_encode($csvData);. It may be an extra http/server request but processing files is much easier.
There are some Javascript libraries that you wouldn't need to run server-side scripts for - JQuery CSV and PapaParse
Alright, So I have this script that uploads a file on drag and drop from the browser using HTML5.
$(function(){
var dropbox = $('#dropbox'),
message = $('.message', dropbox);
dropbox.filedrop({
// The name of the $_FILES entry:
paramname:'pic',
maxfiles: 50,
maxfilesize: 50,
url: 'post_file.php',
uploadFinished:function(i,file,response){
$.data(file).addClass('done');
// response is the JSON object that post_file.php returns
},
error: function(err, file) {
switch(err) {
case 'BrowserNotSupported':
showMessage('Your browser does not support HTML5 file uploads!');
break;
case 'TooManyFiles':
alert('Too many files! Please select 20 at most! (configurable)');
break;
case 'FileTooLarge':
alert(file.name+' is too large! Please upload files up to 10mb (configurable).');
break;
default:
break;
}
},
//// Called before each upload is started
// beforeEach: function(file){
// if(!file.type.match(/^image\//)){
// alert('Only images are allowed!');
//
// // Returning false will cause the
// // file to be rejected
// return false;
// }
// },
uploadStarted:function(i, file, len){
createImage(file);
},
progressUpdated: function(i, file, progress) {
$.data(file).find('.progress').width(progress);
}
});
var template = '<div class="preview">'+
'<span class="imageHolder">'+
'<img />'+
'<span class="uploaded"></span>'+
'</span>'+
'<div class="progressHolder">'+
'<div class="progress"></div>'+
'</div>'+
'</div>';
function createImage(file){
var preview = $(template),
image = $('img', preview);
var reader = new FileReader();
image.width = 100;
image.height = 100;
reader.onload = function(e){
// e.target.result holds the DataURL which
// can be used as a source of the image:
image.attr('src',e.target.result);
};
// Reading the file as a DataURL. When finished,
// this will trigger the onload function above:
reader.readAsDataURL(file);
message.hide();
preview.appendTo(dropbox);
// Associating a preview container
// with the file, using jQuery's $.data():
$.data(file,preview);
}
function showMessage(msg){
message.html(msg);
}
});
It runs on with the following post_file.php
<?php
// If you want to ignore the uploaded files,
// set $demo_mode to true;
$demo_mode = false;
$upload_dir = 'uploads/';
//$allowed_ext = array('jpg','jpeg','png','gif','doc','docx','pdf','xls','xlsx','pptx','ppt','rtf','txt','mp4','css','rar','zip','exe','mp3','wav');
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
exit_status('Error! Wrong HTTP method!');
}
if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
$pic = $_FILES['pic'];
//if(!in_array(get_extension($pic['name']),$allowed_ext)){
// exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
//}
if($demo_mode){
// File uploads are ignored. We only log them.
$line = implode(' ', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);
exit_status('Uploads are ignored in demo mode.');
}
// Move the uploaded file from the temporary
// directory to the uploads folder:
if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
exit_status('File was uploaded successfuly!');
}
}
exit_status('Something went wrong with your upload!');
// Helper functions
function exit_status($str){
echo json_encode(array('status'=>$str));
exit;
}
function get_extension($file_name){
$ext = explode('.', $file_name);
$ext = array_pop($ext);
return strtolower($ext);
}
?>
Now the problem is I have a certain JSON url that when I open it sends a text message to a certain number. I'm trying to append that URL somewhere in the script so that it runs that url everytime an upload is made.
Any ideas?
$URL = "http://www.api.com/api.php?data=mydata";
$data = file_get_contents($URL);
This solves it.