Saving HTML 5 Canvas as Image on the server using ASP.NET - javascript

I need some help here..
Im trying to save a canvas image after drawing..
following this example (http://www.dotnetfunda.com/articles/article1662-saving-html-5-canvas-as-image-on-the-server-using-aspnet.aspx)
$("#btnSave").click(function () {
var image = document.getElementById("canvas").toDataURL("image/png");
image = image.replace('data:image/png;base64,', '');
$.ajax({
type: 'POST',
url: "../../Home/UploadImage?imageData=" + image,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
alert('Image saved successfully !');
}
});
});
the controller:
public void UploadImage(string imageData)
{
string fileNameWitPath = path + DateTime.Now.ToString().Replace("/", "-").Replace(" ", "- ").Replace(":", "") + ".png";
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(imageData);
bw.Write(data);
bw.Close();
}
}
}
But when im trying to convert form base64 the string that is passed like parameter in method, throw an error
Invalid length for a character array Base-64.

You can't post data with querystring parameters
Try this;
$("#btnSave").click(function () {
var image = document.getElementById("canvas").toDataURL("image/png");
image = image.replace('data:image/png;base64,', '');
$.ajax({
type: 'POST',
url: "../../Home/UploadImage",
data: '{ "imageData" : "' + image + '" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
alert('Image saved successfully !');
}
});
});

In that example, the author has posted the image data using a hidden field, notice below line of code in his article
<input type="hidden" name="imageData" id="imageData" />
http://www.dotnetfunda.com/articles/show/2665/saving-html-5-canvas-as-image-in-aspnet-mvc
And on click of the button, he is submitting the form after getting canvas data to the hidden field so follow the same approach. As written by Mehmet, querystring has limitations and its prone to be modified as it goes via url.

Instead of this
image = image.replace('data:image/png;base64,', '');
use this:
image = image.substr(23, image.length);
remove the leading characters up to the first comma (use any dev tool to see what you posted).

Related

Laravel - Get data from Ajax Post request

I want to upload images with ajax. I convert the image to a base64 string. Posting the data works, but how do I get it on the server (I'm using Laravel 5.4)? I can do $request->all() what gives me an array with all the images base64 strings combined. I cannot do anything with that because whatever I do with that array will result in a 500 error.
This is my script to convert the images and post them.
let queue = [];
function addFile(input) {
let files = input.files,
j = files.length,
file;
for (i = 0; i < j; i += 1) {
let reader = new FileReader();
reader.onloadend = function (e) {
$('#upload-InnerPanel').append(
"<div class='upload-ItemPanel'><img class='upload-ImagePreview' src='" + e.target.result + "' > </div>");
queue.push(reader.result);
};
file = files[i];
reader.readAsDataURL(file);
}
}
$('#upload-ButtonSelect').on("click" , function () {
$('#upload-UploadInput').click();
});
$('#upload-UploadInput').change(function () {
addFile(this);
});
$('#upload-ButtonUpload').click(function () {
$.ajax({
url: "/admin/upload",
type: "POST",
data: queue,
processData: false,
error: function(xhr, status, error) {
let err = xhr.responseText;
//console.log(err);
$('#upload-InnerPanel').append("<iframe width='600' height='500' src='" + err +"'> </iframe>")
},
success: function (xhr) {
console.log(xhr);
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
});
This is my controller:
public function upload(Request $request)
{
return var_dump($request->all());
}
That works, sort of, because My response is one long base64 in an array with just 1 item. Even if I add multiple images I just get one item in the array instead of three. It now combines them all in to one. Also, as I said. I cannot do anything with that array what does not result in a 500 error.
So my question is:
How do I get it to work so I can post multiple items instead of one and get the data on the backend?
You could add each file as a new input on your form, so that you have them separately on the back end.
In your addFile Javascript, instead of queue.push(reader.result), append a hidden input with the results:
reader.onloadend = function (e) {
// ... your code
// Update the form selector to suit your form
$('form').append('<input type="hidden" name="files[]" value="' + reader.result + '">');
};
Then in your ajax form submission:
$('#upload-ButtonUpload').click(function () {
// Again update the form selector to suit your form
var data = $('form').serialize();
$.ajax({
url: "/admin/upload",
type: "POST",
data: data,
// ... etc

Javascript and PHP. Sending Multiple Array to PHP Using Ajax and Convert it to PHP Array

I need some help. I am trying to send multiply array of width and length to php, straight forward. I don't want to save it to any HTML field, however it's not working. I am getting the width and length from html text are and convert it to a number and then add it to an array in javascript.
Here is the code for that
var widthL = [];
var lengthL = [];
var widths = document.wall.width.value;
var lengths = document.wall.length.value;
var wNumber = Number(widths);
var lNumber = Number(lengths);
widthL.push(JSON.stringify(wNumber));
lengthL.push(JSON.stringify(lNumber));
This is the Ajax code I am using to send it to PHP
$.ajax( {
type: "POST",
url: "./Summary.php",
data: {"widths": widthL, "lengths" : lengthL},
cache: false,
success: function (response) {
console.log("This is the width", widthL, " This is the length", lengthL);
}
});
In PHP I am using this code to receive it. But I am not getting things back.
<?php
$lengths = json_decode($_POST['lengths']);
$widths = json_decode($_POST['widths']);
echo 'This is the width: '.$widtsL;
echo 'This is the length: '.$lengths;
?>
I was hopping that someone could help me out here.
First you should specify the content type in the ajax POST:
$.ajax( {
type: "POST",
url: "./Summary.php",
contentType: "application/json; charset=UTF-8", // Add content type
data: {"widths": widthL, "lengths" : lengthL},
cache: false,
success: function (response) {
console.log("This is the width", widthL, " This is the length", lengthL);
}
});
then in PHP:
$request_body = file_get_contents('php://input'); //This reads the raw POST data
$json = json_decode($request_body); // Then parse it to JSON
$lengths = $json->lengths;
$widths = $json->widths;
please add a POST parameter name as dataType,type it value JSON,
the Ajax data param value use key=value&key=value format
then in php file enter debug code

Download PDF Using AJAX and TCPDF

I am trying to make a post via AJAX to a PHP script that will then create a PDF.
function getPDF() {
var hashed_center_ids = JSON.parse($('#hashed_center_ids').val());
var print_data = $('.print-options:checked').map(function() {
return this.value;
}).get();
$.ajax({
type: "POST",
url: "<?=site_url('front_office/get_pdf/')?>",
data: {hashed_center_ids : hashed_center_ids, print_data : print_data},
dataType: "text",
success: function(response) {
console.log(response)
var blob=new Blob([response]);
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="test"+new Date()+".pdf";
link.click();
}
});
}
Once my PDF has been created I return it like so:
return $pdf;
However this just returns,
Message: Object of class TCPDF could not be converted to string
in the chrome console.
Can anybody help me?

Upload properly encoded (base64?) image to SharePoint with AngularJS

I am able to upload an image file to SharePoint, but it is not being recognized as an image. I have tried utilizing the following directive based on research that states images need to be base64 encoded when uploaded into SharePoint, but it still uploads a file that appears to be corrupt: https://github.com/adonespitogo/angular-base64-upload
I am happy to use this directive, but am unsure of how to pass what I need into SharePoint's REST API.
The original iteration I had does not use this directive, but is more of a straight upload attempt.
What I need to achieve is as follows:
1) Successfully upload an image without it being "corrupted", and does this require base64 encoding/how do I achieve this?
2) Upload images by their name (not "test.jpg") and have some metadata (ex. upload an image with the title or department name it belongs to)
Iteration 1: No Directive
Here is my HTML (Please note that the controller is tied to the page via ng-route):
<div class="col-md-12">
<form>
<input type="file" onchange="angular.element(this).scope().filesChanged(this)" data-ng-model="files" multiple>
<button data-ng-click="upload()">Submit</button>
<li data-ng-repeat="file in files">{{file.name}}</li>
</form>
</div>
Here is my controller:
$scope.filesChanged = function (elm) {
$scope.files = elm.files
$scope.$apply();
}
$scope.upload = function () {
var fd = new FormData()
angular.forEach($scope.files,function(file){
fd.append('file',file)
})
$http.post("/sites/asite/_api/web/lists/getByTitle('Images')/RootFolder/Files/add(url='test.jpg',overwrite='true')", fd,
{
transformRequest: angular.identity,
headers: {
'Content-Type':undefined, 'X-RequestDigest': $("#__REQUESTDIGEST").val()}
}).success(function (d) {
console.log(d);
});
}
UPDATE: I believe the issue is isolated to my $http post to SharePoint. Using the directive mentioned above, I am able to output the base64, but am unsure how to pass this into my post for upload.
Iteration 2: Using Directive
Here is my current HTML using the https://github.com/adonespitogo/angular-base64-upload directive:
<form>
<input type="file" data-ng-model="files" base-sixty-four-input>
<button data-ng-click="upload()">Submit</button>
</form>
My controller that is posting the corrupted image files to SharePoint:
$scope.upload = function () {
console.log($scope.files); // Output result from upload directive
$http({
method: 'POST',
url: "/sites/ens/_api/web/lists/getByTitle('Report Images')/RootFolder/Files/add(url='" + $scope.files.filename +"',overwrite='true')",
headers: {
'Content-Type': false ,
'X-RequestDigest': $("#__REQUESTDIGEST").val()
},
data: $scope.files,
}).success(function (data) {
console.log(data);
});
}
Update 2: Using SP.RequestExecutor as follows creates the same result. A file upload but not rendering. This happens for images and documents:
Iteration 3: Using Directive and SP.RequestExecutor
$scope.upload = function () {
var dataURL = 'data:' + $scope.files.filetype + ';' + 'base64,' + $scope.files.base64;
var createitem = new SP.RequestExecutor("/sites/asite");
createitem.executeAsync({
url: "/sites/asite/_api/web/lists/getByTitle('Images')/RootFolder/Files/add(url='" + $scope.files.filename + "')",
method: "POST",
binaryStringRequestBody: true,
body: dataURL,
success: fsucc,
error: ferr,
state: "Update"
});
function fsucc(data) {
alert('success');
}
function ferr(data) {
alert('error\n\n' + data.statusText + "\n\n" + data.responseText);
}
}
Update 3: Using .ajax as follows, it will successfully post the image, but when using $http, it corrupts the image.
Iteration 3: Using .Ajax (works)
function uploadFileSync(spWebUrl , library, filename, file)
{
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE)
{
var buffer = evt.target.result;
var completeUrl = spWebUrl
+ "/_api/web/lists/getByTitle('"+ library +"')"
+ "/RootFolder/Files/add(url='"+ filename +"',overwrite='true')?"
+ "#TargetLibrary='"+library+"'&#TargetFileName='"+ filename +"'";
$.ajax({
url: completeUrl,
type: "POST",
data: buffer,
async: false,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
},
complete: function (data) {
//uploaded pic url
console.log(data.responseJSON.d.ServerRelativeUrl);
$route.reload();
},
error: function (err) {
alert('failed');
}
});
}
};
reader.readAsArrayBuffer(file);
}
Iteration 4: Using $http (corrupts image)
function uploadFileSync(spWebUrl , library, filename, file)
{
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
var buffer = evt.target.result;
var completeUrl = spWebUrl
+ "/_api/web/lists/getByTitle('" + library + "')"
+ "/RootFolder/Files/add(url='" + filename + "',overwrite='true')?"
+ "#TargetLibrary='" + library + "'&#TargetFileName='" + filename + "'";
$http({
url: completeUrl,
method: "POST",
data: buffer,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
}
}).success(function (data) {
//uploaded pic url
//console.log(data.responseJSON.d.ServerRelativeUrl);
$route.reload();
}).error(function (err) {
alert(err);
});
}
};
reader.readAsArrayBuffer(file);
}
Yes, you must do the base64 encoding.
Following this article, your filesChanged will be function for base64 encoding:
$scope.filesChanged = function (input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
//Sets the Old Image to new New Image
$('#photo-id').attr('src', e.target.result);
//Create a canvas and draw image on Client Side to get the byte[] equivalent
var canvas = document.createElement("canvas");
var imageElement = document.createElement("img");
imageElement.setAttribute('src', e.target.result);
canvas.width = imageElement.width;
canvas.height = imageElement.height;
var context = canvas.getContext("2d");
context.drawImage(imageElement, 0, 0);
var base64Image = canvas.toDataURL("image/jpeg");
//Removes the Data Type Prefix
//And set the view model to the new value
$scope.data.Photo = base64Image.replace(/data:image\/jpeg;base64,/g, '');
}
//Renders Image on Page
reader.readAsDataURL(input.files[0]);
}
};
My advice to you is also to change ng-model from $scope.files to $scope.data.Photo to avoid problems with scope and add an id in your input tag. (in this case id="photo-upload")
So, your HTML for upload will look like:
<input type="file" onchange="angular.element(this).scope().filesChanged(this)" data-ng-model="data.Photo" id="photo-upload" multiple>
And for representing your uploaded pic, in your case, you can use this:
<img ng-src="data:image/jpeg;base64,{{data.Photo}}" id="photo-id"/>
I'm just not sure for multiple upload, but for single upload it works great for me.
Hope this will help you to solve your problem with SharePoint.
Good luck!

Can't save image via HTML canvas

I'm having difficulties saving my canvas. I'm new to javascript so I think it could be a syntax issue.
I've got some vars saved in a function:
var imageView = document.getElementById("imageView");
var canvasData = imageView.toDataURL("image/png");
var postData = "canvasData="+canvasData;
If I add the following line it displays the image correctly:
imgData = $('#i').append($('<img/>', { src : canvasData }));
However, I have another function that I want to pass the base64 code in so I added:
var the_data = "test= "+imageView.toDataURL("image/png");
It does print out a base64 code, but just the blank canvas (not with the drawing the user has added).
If I add the following it doesn't work:
var the_data = "test= "+canvasData;
What am I doing wrong?
This is a basic jsfiddle of what I'm trying to do: http://jsfiddle.net/sMSeX/
Just a little hint from my side for uploading HTML5 canvas image data:
I am working on a project for a print-shop and had some problems due to uploading images to the server that came from an HTML5 canvas element. I was struggling at least for one hour and I did not get it to save the image correctly on my server.
I get the image data as Base64 decoded from the canvas element via
var can = document.getElementsByTagName('canvas');
var dataURL = can[0].toDataURL("image/jpg");
//dataURL = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
console.log('data url: '+dataURL);
Once I set the
contentType option of my jQuery ajax call to 'application/x-www-form-url-encoded' :
$.ajax({
url: 'index.php?page=upload-image',
type: 'post',
contentType: 'application/x-www-form-urlencoded',
//data: '{ "imageData" : "' + dataURL + '" }',
data: dataURL,
beforeSend: function() {
$('.text-danger').remove();
},
complete: function() {
},
success: function(json) {
console.log('upload complete');
}
});
everything went the right way and the base64-encoded data was interpreted correctly and successfully saved as an image.
Maybe someone helps that!

Categories