Can't post larg canvas image via jquery to server side - javascript

Here my jquery code:
var image = document.getElementById("canvas").toDataURL("image/png");
$.ajax({
type: "POST",
url: "imageup.php",
data: {image:image, title:getTitle, infos:informations},
success: function (response) {
alert(response);
}
});
For small images this work perfectly, but when i use a larg image, i odn't get the full base64 code of the image itself !
I tried this solution here:
https://stackoverflow.com/a/5061163/7232957
I devided the base64 image into many part and add them into array, and then send it to server side ! but all time same thing ! not get the full image.
Any one have a trick in order to solve this annoying problem ?
Is there a way to send html5 canvas image as file to server side ?
I already configured my apache server:
post_max_size = 500 Mo
upload_max_filesize = 500 Mo

Related

Base64 Upload Image Issue

Sorry for the long question, but I wanted to express it as well as I could, and ask it in a way that is understood easily. I have a program that allows a user to crop an image using croppie.js in JavaScript, and send the image to a Hunchentoot server on the backend running a Lisp program. I am having an issue saving the Base64 image to a .png file once the user uploads it. Once the post request is sent to the server I am getting the Base64 image as a string, removing invalid characters from the Base64 request by creating a subsequence of the string without the heading sent by the post request and also substituting the "%" character for the "+" character to make the Base64 valid. Next I remove the substring +3D+3D at the end of my string, because the s-base64 library that I am using in Common Lisp complains +3D+3D is invalid padding, and I replace it with "==" which is considered valid padding. Next I create a byte array by using the s-base64 library to translate the Base64 string to a byte array, and store it in a variable. Then I loop through the byte array and write each byte to the output file. When that is finished I decided to print the end of the byte array to the console so that I could see if the output and ending padding is valid, which it appears to be. Here is that part of the code, with comments to make it clearer:
(define-easy-handler (handle-image :uri "/handle-image.html") ()
(let ((data-source (hunchentoot:raw-post-data :force-text t))) ;get Base64 string
(let ((new-string (subseq data-source 36))) ;create a subsequence of Base64 string
(let ((final-string (substitute #\+ #\% new-string))) ;substitute % for +
(let ((end (search "+3D+3D" final-string))) ;find the invalid padding
(setf final-string (concatenate 'string (subseq final-string 0 end) "==")) ;add valid padding
(let ((byte-array (with-input-from-string (in final-string) ;create byte array (or simple-vector) out of Base64 string
(decode-base64-bytes in))))
(with-open-file (out "path/path/path/path/profile-image.png" ;create output stream to store file
:direction :output
:if-exists :supersede
:element-type 'unsigned-byte)
(dotimes (i (length byte-array)) ;write each byte from the byte array to output stream
(write-byte (aref byte-array i) out)))) ;close stream
(format t "!!!!!!!!: ~a" (subseq final-string (- (length final-string) 30))))))) ;print ending to console to ensure proper padding
"Upload Successful") ;send response to client
And here is some of my JavaScript code:
$(document).ready(function(){
$image_crop = $('#image_demo').croppie({
enableExif: true,
viewport: {
width:200,
height:200,
type:'square' //circle
},
boundary:{
width:300,
height:300
}
});
As you can see, I first create the cropper. I allow the user to have a 200 x 200 square to crop, and the total size of the cropping space is 300 x 300. There are no issues with that part of the code:
$('#upload_image').on('change', function(){
var reader = new FileReader();
reader.onload = function (event) {
$image_crop.croppie('bind', {
url: event.target.result
}).then(function(){
console.log('jQuery bind complete');
});
}
Above I bind the image they've uploaded to the cropper (like if you upload a Facebook image), when they select a file. Again, no issues:
reader.readAsDataURL(this.files[0]);
$('#uploadImageModal').modal('show');
Above I read the file that they've selected and then the modal "pops up" as if you're cropping a Facebook or Instagram photo:
$('.crop_image').click(function(event){
$image_crop.croppie('result', {
type: 'canvas',
size: 'viewport'
}).then(function(response){
$.ajax({
url:"handle-image.html",
type: "POST",
data:{"image": response},
success:function(data){
$('#uploadImageModal').modal('hide');
$('#uploaded_image').html(data);
}
});
})
});
Above I upload the ajax request, and if the upload was successful they will get a message from the server that it was success, and I hide the modal for image cropping as well.
Now the issue is that the image is simply blank. I know that the Base64 is valid because I used a Base64 conversion tool to see if the string was valid. I also went back and did my research in regards to Bits, Bytes, Pixels, and dimensions of images to see how the computer interacts with them, so i'm not sure why my image is simply displaying blank. Here is a look at what the cropper looks like on my website:
The bind is working, and then I get the message that the upload was successful. BUT after writing the image and viewing it in the file system it is either a blank image, or will sometimes say that the image type is not supported.
The reason why I am tagging PHP in this post is because I am sure some people have had similar issues in PHP with uploading a cropped image via ajax, and some of those solutions might be applicable in this case, but obviously will require me translating the solution to the lisp syntax. My assumption is that something is wrong with my code when I translate the string to a byte array and write it to a file, but I thought it'd be good to post other sections of my code if I am overlooking something.
As Brad commented, you should first try to use binary uploads directly.
That aside: if you encounter a % in a base64-encoded string, it most likely means that the entire thing is additionally URL-encoded. A quick apropos search gave do-urlencode as a library to decode that. Replacing % with + makes valid base64, but the result does not necessarily represent valid jpg.
Also: use let* instead of nested let forms. Maybe use write-sequence instead of byte-wise output.
Thanks to the answer from #Brad and #Svante I was able to solve the problem. I decided to put the image that I want to upload within a form element, add the blob image from the canvas as FormData for the form, and then send the FormData via an ajax post request:
$('.crop_image').on('click mousedown touchstart', function(event){ //When the crop image button is pressed event.
$image_crop.croppie('result', { //Get the result of the cropper
size: 'viewport', //Set the size to the viewport size (180 x 120)
format: 'png', //.png format
type: 'blob'
}).then(function (blob){
$form = $('#uploadForm');
var fd = new FormData($form);
fd.append('upload_image', blob);
$.ajax({
url: "handle-image.html",
type: "POST",
data: fd,
processData: false,
contentType: false,
success: function (data){
$('#uploadImageModal').modal('hide');
$('#uploaded_image').html(data);
}
});
})
});
Here I just decided to change the croppie result from the type "canvas"to the type "form", and specify that it will be a .png file. From there I added the form data from my newly created form to the .ajax request and went from there. Thanks to #Brad and #Svante for the help here.

AJAX - Weird characters in img tag after request response

I'm have trouble solving an issue with an AJAX request I'm making (I'm new to AJAX by the way). I have an API set-up and I'd like to retrieve a png image using an Authorization header which uses a token that I supply (which is stored in local storage). So for example, if i were to access the image with the Auth header then I would do this...
$.ajaxSetup({headers: {"Authorization" : localStorage.token}});
I'm able to retrieve the image. I can see it in the "Network" tab in Chrome, but when I append it to my div using this below...
$.ajax({
//Use commas for several parameters
type: 'GET',
url: *url of image*,
contentType: 'image/png',
success: function (data) {
binary = data;
$("#image").attr("src", 'data:image/png;base64,'+ data);
}
...it comes out in this weird character format (as seen below):
div id="image" src="data:image/png;base64, PNG
IHDRww^ÀþIDATxÚìÝ|ÔWº?þ½¿ÿ½Ý.ÅâÉd2îdâ®BB ÁÝÝ
)îÞbÅÝ¥TÐzi)Ô ÞRÙn»rï]»+w·{þçùÌ<Ãd]ùýV¾çõz¿H&I°Ï÷ç<çï}OÊø;æO1ªzhÔÀdÆþKȤ!......."
etc
I'd like it to come back as an image or a b64 string which I can simply put into the src param. I've searched online everywhere and cannot seem to find an answer.
Any ideas? I appreciate your time greatly.
This is the response I receive
Your code is downloading the image, which is in binary format.
You need to encode the binary to base64 in order to display the image in base64. Use btoa as explained in this answer: https://stackoverflow.com/a/247261/2223027
It seems like you are getting image file in binary data format and not the base64 format as you are expecting to put in the img tag src attribute.
If you do have image url you can put it in the img src directly no need of ajax call.

Save a canvas as an image to the server in ASP.net

I have a page with a google map in it and some data in a couple of divs, I need the user to click "Grab Screenshot" button and that should save the screenshot of the user's page and save it to the server.
I tried through Html2Canvas, but it is not allowing me to convert canvas to dataurl i.e in my javascript function, I used this:
function GenerateImage()
{
html2canvas($('#mainDiv'), {
onrendered: function(canvas) {
//this appends the canvas(screenshot) to the page, this is working fine
document.body.appendChild(canvas);
//this is not working,
//Error: SecurityError: The operation is insecure.
var image = canvas.toDataURL('image/png');
image.crossOrigin = 'anonymous';
var imgdata = image.replace(/^data:image\/(png|jpg);base64,/, '');
$.ajax({
url: '******',
data: {
imgdata:imgdata
},
type: 'post',
success: function (response) {
console.log('Success');
}
});
}
});
}
I did research, I found out it is some CORS issue, but I am unable to figure out a solution.
So, I was wondering if I can do a screenshot using ASP.net, is that possible? Thanks in advance.
I was able to successfully do it using the proxy. I had an issue with a custom marker icon from a different website on the map. That was causing the canvas to taint. I moved the image to my website and changed the path, the "tainted canvases may not be exported" error went away.

Saving canvas with background image to server with html2canvas

I currently have a script that successfully creates an image from canvas including its containing Div background image by using html2canvas. I also have a script that can save the canvas as an image to the server using the canvas2image plugin but the background doesn't show up.
The problem I'm having is when I try to combine the two so that I can save the Div bg and canvas as an image to the server, nothing happens which I believe is due to the canvas2image plugin not firing.
The code I have with both plugins combined is here.
function exportAndSaveCanvas() {
html2canvas($("#containingDiv"), {
background:'#fff',
onrendered: function(canvas) {
// var imgData = canvas.toDataURL('image/jpeg'); <--This would create the image needed
//but I replaced with the line below to tie in the two plugins
var screenshot = Canvas2Image.saveAsPNG(canvas, true);
canvas.parentNode.appendChild(screenshot);
screenshot.id = "canvasimage";
data = $('#canvasimage').attr('src');
canvas.parentNode.removeChild(screenshot);
// Send the screenshot to PHP to save it on the server
var url = 'upload/export.php';
$.ajax({
type: "POST",
url: url,
dataType: 'text',
data: {
base64data : data
}
});
}
});
}
The code for export.php which upload the image to the server is here
<?php
$data = $_REQUEST['base64data'];
//echo $data;
$image = explode('base64,',$data);
file_put_contents('../uploadimg/myImage.jpg', base64_decode($image[1]));
?>
I was hoping to be able to combine the two plugins to work together and get my canvas with Div background save to the server but it looks like the canvas2image plugin doesn't fire.
Thanks!
Write the background image into the canvas before you write the other image. The MDN page about writing an image to a canvas should have you covered: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images
As an aside, I'm not sure why you're using a plugin to do anything you get for free with the native canvas API.
dtanders said "As an aside, I'm not sure why you're using a plugin to do anything you get for free with the native canvas API."
This got me thinking that I was making it more difficult than it needed to be so I stripped away some code. The script below does just what I need.
function exportAndSaveCanvas() {
html2canvas($("#containingDiv"), {
background:'#fff',
onrendered: function(canvas) {
var imgData = canvas.toDataURL('image/jpeg');
var url = 'upload/export.php';
$.ajax({
type: "POST",
url: url,
dataType: 'text',
data: {
base64data : imgData
}
});
}
}); //End html2canvas
} // End exportAndSaveCanvas()

how to post Base64 encoded image to server using $.ajax?

I am making a phonegap app, in which the user submits a photo from his camera, i get it in a Base64 encoding form.
var posData=extImage1;
$.ajax({
type: 'POST',
data: posData,
timeout:50000,
url: 'http://192.168.137.1/bee/services/add_photo.php',
success: function(data){
alert(data);
addToList();
},
error: function(){
alert('Please check your internet connection');
}
});
server side the code is saved to the database, but when selected and used as div background; it won't work no matter what!
BG='url(' + "data:image/jpeg;base64," + item.car_intImage3+ ')';
$('#item').css('background',BG);
why this is happening ? my guess is that during posting the data it got scrambled somehow.
I tried to save the image on server using the code from this question, but it just gives a corrupted image.
Update:
Using this decoder i submitted the posted 64 code and it also gives corrupted image. i think that means that there is something wrong with my post method. any suggestions?
It would be a lot cleaner and easier if you use Dropzone.js
Take a look at Dropzone.js Implementation. It is quite easy
This is how you can instantiate it
var myDropzone = new Dropzone("div#myId", { url: "/file/post"});
You can also listen to a lot of events like Adding a file, Removing a file
For Ex:
Dropzone.options.myAwesomeDropzone = {
init: function() {
this.on("addedfile", function(file) { alert("Added file."); });
}
};
EDIT: The Above solutions will work if you are storing the image in your disk and just the image location in your database. In fact it would be a lot better if you do this way.
Now coming to your method of working with images, You would want to go through this link how-can-i-store-and-retrieve-images-from-a-mysql-database-using-php which has a straight forward answer
Also, Check the datatype that you are using, may be its truncating he encoded data that you are storing in the database and hence you might be getting corrupted images. Also check with the above method of storing the images in the database mentioned in the link.
Hope this solves your problem

Categories