base64_decode fail when decoding - javascript

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 !

Related

python django - Images are blank when written using decoded base64

My django website aims at allowing users to combine different clothing picture on one single canvas.
However, the saved image is blank.
I have applied one fiddle, please see here.
I've used the methods recommended by some forums.
Here is the views.py
#csrf_protect
#csrf_exempt
def savewearingimg(request):
imgEncodeString = request.POST.get('imgBase64')
if request.method == 'POST' and request.is_ajax():
singleItemNames = request.POST.getlist('singleItemNames[]')
saveWearingName = request.POST.get('saveWearingName') #string
positionsX = request.POST.getlist('positionsX[]')
positionsY = request.POST.getlist('positionsY[]')
userWidths = request.POST.getlist('sizes[]')
imgEncodeString = request.POST.get('imgBase64').partition(",")[2]#for header removing
img64Data = base64.b64decode(imgEncodeString) #other decoding fundctions failed
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
preFileStr = os.path.join(BASE_DIR, "media\\photos\\wearing\\")
poFileStr=str(request.user)+'_itemName_'+saveWearingName+'.jpg'
filename = preFileStr +poFileStr
with open(filename, 'wb') as f:
f.write(img64Data)
return render(request,'combinewearing.html')
And here is part of the javascript combinewearing.js
$(function() {
canvas = document.getElementById('save-canvas');
context = canvas.getContext('2d');
});
$('#saveWearingBtn').click(function(){
drawToSave(alreadyPutImg,originalWidths);
});
function drawToSave(alreadyPutImg,originalWidths){
loadImagesMike(sources, function(images_) { //the original author is Mike
for(var i=0; i<ImgPutArr.length; i++ ){
var img_iter = ImgPutArr[i];
context.drawImage(images_[i],img_iter.x,img_iter.y,img_iter.w,img_iter.h);
console.log('images_[i]: '+images_[i] );//[object HTMLImageElement]
i++;
}
});
var myDataURL = canvas.toDataURL();
$.ajax({
type: "POST",
url: "/savewearingimg/",
data: {
'csrfmiddlewaretoken': "{{ csrf_token }}",
'imgBase64': myDataURL,
'singleItemNames': alreadyPutName,//array storing what users have added to the canvas
'saveWearingName':$('#saveWearingName').val(), //end-users can customized his/her desired wearing title
'positionsX':positionsX, //position array storing every clothing pictures
'positionsY':positionsY,
'sizes':sizes,
},
}).done(function(o) {
alert('saved');
console.log('saved');
});/*end ajax*/
}
/*sources is an array storing all the user-selected pictures absolute path*/
function loadImagesMike(sources, callback) {
var images = [];
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
There is no error message. Only the image is blank.
However, if I follow the same steps and same string as this linksuggests, the image would not be blank.
So I suppose that the problem is due to the string's content. My failed
string content links to this google doc link(Correct me if I'm wrong, thank you.)
I've just found that this rectangle will show up in the image....
So what should I adjust?
context.rect(20, 20, 150, 100);
context.stroke();
I have solved this problem by moving THIS PART to the interior of the loadImagesMike() function (inside drawToSave())
THIS PART---->
var myDataURL = canvas.toDataURL();
$.ajax({
type: "POST",
url: "/savewearingimg/",
data: {
'csrfmiddlewaretoken': "{{ csrf_token }}",
'imgBase64': myDataURL,
'singleItemNames': alreadyPutName,//array storing what users have added to the canvas
'saveWearingName':$('#saveWearingName').val(), //end-users can customized his/her desired wearing title
'positionsX':positionsX, //position array storing every clothing pictures
'positionsY':positionsY,
'sizes':sizes,
},
}).done(function(o) {
alert('saved');
console.log('saved');
});/*end ajax*/
THIS PART is moved after the for loop, and it is inside the loadImagesMike() function.

Download stopped working in jquery-1.9.1.min.js?

I have a function in my javascript file for downloading an annotated canvas and then moving it to the server.The rest of the jquery is working fine .. but for some reason these particular functions have stopped working.
$("#ContentPlaceHolder1_btnNext").click(function () {
var canvas = paper.project.activeLayer.view.element;
var img = $(canvas).parent().find('img')[0];
// var name = $("#ContentPlaceHolder1_Label9").text();
var name = $("#ContentPlaceHolder1_HiddenField1").val();
var mergeCanvas = $('<canvas>')
.attr({
width: $(img).width(),
height: $(img).height()
});
var mergedContext = mergeCanvas[0].getContext('2d');
mergedContext.clearRect(0, 0, $(img).width(), $(img).height());
mergedContext.drawImage(img, 0, 0);
mergedContext.drawImage(canvas, 0, 0);
//alert(canvas);
self.downloadCanvas(mergeCanvas[0], name);
//alert(mergeCanvas[0]);
//alert(name);
});
this.downloadCanvas = function (canvas, filename) {
/// create an "off-screen" anchor tag
var lnk = document.createElement('a'), e;
/// the key here is to set the download attribute of the a tag
lnk.download = filename;
/// convert canvas content to data-uri for link. When download
/// attribute is set the content pointed to by link will be
/// pushed as "download" in HTML5 capable browsers
lnk.href = canvas.toDataURL();
if (filename != "") {
/// create a "fake" click-event to trigger the download
if (document.createEvent) {
e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false,
false, 0, null);
lnk.dispatchEvent(e);
// save image to server
$.ajax({
type: 'POST',
url: 'home.aspx/MoveImages',
data: '{ "imageData" : "' + filename + '" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
//alert("Done, Picture Uploaded.");
}
});
It was working perfectly a month back .. But it has stopped working and I am not able to figure out what could have changed?
the following scripts are used :
<script type="text/javascript" src="https://code.jquery.com/jquery-
1.8.2.min.js"></script>
<script src="js/jquery-1.9.1.min.js" type="text/javascript"></script>
webmethod :
[System.Web.Services.WebMethod(EnableSession = true)]
public static void MoveImages(string imageData)
{
string fileName = "";
// get computer name
string clientMachineName;
clientMachineName = Dns.GetHostName();
string computerName = clientMachineName.Split('-').First();
// get download location
string pathUser = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string sourcePath = Path.Combine(pathUser, "Downloads");
string pathstring = #"D:\........";
string class = HttpContext.Current.Session["class"].ToString().Trim();
string sub = HttpContext.Current.Session["subject"].ToString().Trim();
string targetPath = System.IO.Path.Combine(pathstring, class);
string pathstring1 = targetPath;
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(pathstring1, sub);
// Use Path class to manipulate file and directory paths.
if (System.IO.Directory.Exists(sourcePath))
{
string[] jpg = System.IO.Directory.GetFiles(sourcePath, "*.jpg");
string[] png = System.IO.Directory.GetFiles(sourcePath, "*.png");
string[] files = jpg.Concat(png).ToArray();
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
if (s.Length > 0)
{
fileName = System.IO.Path.GetFileName(s);
sourceFile = Path.Combine(sourcePath, fileName);
//destFile = System.IO.Path.Combine(targetPath, fileName);
destFile = System.IO.Path.Combine(destFile, fileName);
if (File.Exists(destFile))
{
File.Delete(sourceFile);
}
else
{
System.IO.File.Move(s, destFile);
}
}
}
}
}
Background.js :
'use strict';
let disableShelf = () => chrome.downloads.setShelfEnabled(false);
chrome.runtime.onInstalled.addListener(disableShelf);
chrome.runtime.onStartup.addListener
(disableShelf);

How do I fix orientation (upload image) before saving in folder (Javascript)?

I try this reference : https://github.com/blueimp/JavaScript-Load-Image
I try like this : https://jsfiddle.net/oscar11/gazo3jc8/
My code javascript like this :
$(function () {
var result = $('#result')
var currentFile
function updateResults (img, data) {
var content
if (!(img.src || img instanceof HTMLCanvasElement)) {
content = $('<span>Loading image file failed</span>')
} else {
content = $('<a target="_blank">').append(img)
.attr('download', currentFile.name)
.attr('href', img.src || img.toDataURL())
var form = new FormData();
form.append('file', currentFile);
$.ajax({
url:'response_upload.php',
type:'POST',
data:form,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log(error)
},
});
}
result.children().replaceWith(content)
}
function displayImage (file, options) {
currentFile = file
if (!loadImage(
file,
updateResults,
options
)) {
result.children().replaceWith(
$('<span>' +
'Your browser does not support the URL or FileReader API.' +
'</span>')
)
}
}
function dropChangeHandler (e) {
e.preventDefault()
e = e.originalEvent
var target = e.dataTransfer || e.target
var file = target && target.files && target.files[0]
var options = {
maxWidth: result.width(),
canvas: true,
pixelRatio: window.devicePixelRatio,
downsamplingRatio: 0.5,
orientation: true
}
if (!file) {
return
}
displayImage(file, options)
}
// Hide URL/FileReader API requirement message in capable browsers:
if (window.createObjectURL || window.URL || window.webkitURL ||
window.FileReader) {
result.children().hide()
}
$('#file-input').on('change', dropChangeHandler)
})
If I uploaded the image, the image saved in the folder still does not use the image that is in its orientation set. I want when I upload a picture, the image stored in the folder is the image that has been set its orientation
It seems that the currentFile sent via ajax is the unmodified currentfFile. How do I get the modified currentFile?
After some researching little bit I found the solution thanks to this great plugin https://github.com/blueimp/JavaScript-Canvas-to-Blob . ( canvas-to-blob.js )
This plugin will convert your canvas to a Blob directly server would see it as if it were an actual file and will get the new(modified) file in you $_FILES array. All you need is call toBlob on the canvas object (img). After that you would get your blob which you then can send in FormData. Below is your updated updateResults() function
function updateResults (img, data) {
var content
if (!(img.src || img instanceof HTMLCanvasElement)) {
content = $('<span>Loading image file failed</span>')
}
else
{
content = $('<a target="_blank">').append(img)
.attr('download', currentFile.name)
.attr('href', img.src || img.toDataURL())
img.toBlob(
function (blob) {
var form = new FormData();
form.append('file', blob, currentFile.name);
$.ajax({
url:'response_upload.php',
type:'POST',
data:form,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log(error)
},
});
},'image/jpeg'
);
result.children().replaceWith(content);
}
}
You want to change some things about image (dimensions, roataion etc) and upload it on to the server but the problem here is that ImageLoad plugin will give the modified image as an canvas means it won't modify the original file selected in
<input type="file" id="file-input">. Since you are sending the file input object in form.append('file', currentFile); your modified file wont get sent but just the original
How to fix?
This is particularity hard you (or plugin) cannot modify anything on <input type="file" id="file-input"> due to browser restrictions neither you can send canvas directly to the server so the only way (used and works great) is to send the data URI of the image as a regular text and then decode it on the server, write it to a file.You might also want to send the original file name since a data URI is pure content and doesn't hold file name
Change
form.append('file', currentFile);
To
form.append('file', img.toDataURL() ); // data:image/png;base64,iVBO ...
form.append('file_name', currentFile.name ); // filename
PHP
$img_data=substr( $_POST['file'] , strpos( $_POST['file'] , "," )+1);
//removes preamble ( like data:image/png;base64,)
$img_name=$_POST['file_name'];
$decodedData=base64_decode($img_data);
$fp = fopen( $img_name , 'wb' );
fwrite($fp, $decodedData);
fclose($fp );
Good luck!

Uploading image file through jQuery with PHP

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;

PDF created with jsPDF won't send to python server through ajax

I am using jsPDF to create a PDF on client side, send it to my python server via ajax call, then send the PDF to myself via email. When I create the jsPDF object with some text:
var doc = new jsPDF();
doc.text(35, 25, "test");
It works, and I get the email with the populated PDF attached. When I try and add an image:
var doc = new jsPDF();
doc.text(35, 25, "test");
doc.addImage(imageDataURL, 0, 50);
The ajax call doesn't go through and I get an error. I have tried just having the image on the page, without the text, but the same error happens. My python controller isn't complaining, mainly because it isn't getting called. When I print the error to the console, it says the responseText is "", and status is 0.
When I download the created PDF with doc.save(), the PDF looks fine. It has the image and the text is the right positions.
My code looks like this:
Javascript:
checkout_button.addEventListener('click', function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src = curr_order.image_url;
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
context.drawImage(image, 0, 0, canvas.width, canvas.height);
var doc = new jsPDF();
doc.text(35, 25, "test");
doc.addImage(canvas.toDataURL('image/jpeg', 1), 'jpeg', 0, 50);
var pdf = doc.output();
//doc.save();
$.ajax('{{=URL('default', 'send_note_PDF')}}', {
data: {
pdf_data: pdf
},
Method: 'POST',
success: function () {
console.log('cool');
},
error: function (data) {
console.log('not cool');
console.log(data);
}
});
});
Python:
def send_note_PDF():
pdf_data = request.vars.pdf_data
file = open('test.pdf', 'w')
file.write(pdf_data)
file.close()
msg = MIMEMultipart()
msg['From'] = 'sending-email#gmail.com'
msg['To'] = 'receiving-email#gmail.com'
msg['Subject'] = 'PDF Test'
body = "test"
msg.attach(MIMEText(body))
file = open('test.pdf', 'rb')
part = MIMEApplication(file.read(), file.name)
part['Content-Disposition'] = 'attachment; filename="%s"' % file.name
msg.attach(part)
mail = smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
mail.starttls()
mail.login('sending-email#gmail.com', 'password')
mail.sendmail('sending-email#gmail.com', 'receiving-email#gmail.com', msg.as_string())
mail.close()
return 'ok'
Do I have to format the output of the doc before I pass it through ajax? I have tried stringifying it and parsing it on the python side. It works without the picture, but whenever that picture is added, it doesn't play nicely.

Categories

Resources