How encode in base64 a file generated with jspdf and html2canvas? - javascript

i'm trying encode the document generated in the attached code, but nothing happens, not generate error but neither encodes the file, and the ajax request is never executed
what is the correct way?
html2canvas(document.getElementById("workAreaModel"), {
onrendered: function(canvas)
{
var img = canvas.toDataURL("image/png");
var doc = new jsPDF("l", "pt", "letter");
doc.addImage(img, 'JPEG',20,20);
var fileEncode = btoa(doc.output());
$.ajax({
url: '/model/send',
data: fileEncode,
dataType: 'text',
processData: false,
contentType: false,
type: 'GET',
success: function (response) {
alter('Exit to send request');
},
error: function (jqXHR) {
alter('Failure to send request');
}
});
}
});

First, jsPDF is not native in javascript, make sure you have included proper source, and after having a peek on other references, I think you don't need btoa() function to convert doc.output(), just specify like this :
doc.output('datauri');
Second, base-64 encoded string is possible to contain ' + ' , ' / ' , ' = ', they are not URL safe characters , you need to replace them or you cannot deal with ajax .
However, in my own experience, depending on file's size, it's easy to be hell long ! before reaching the characters' length limit of GET method, encoded string will crash your web developer tool first, and debugging would be difficult.
My suggestion, according to your jquery code
processData: false,
contentType: false
It is common setting to send maybe File or Blob object,
just have a look on jsPDF, it is availible to convert your data to blob :
doc.output('blob');
so revise your code completely :
var img = canvas.toDataURL("image/png");
var doc = new jsPDF("l", "pt", "letter");
doc.addImage(img, 'JPEG',20,20);
var file = doc.output('blob');
var fd = new FormData(); // To carry on your data
fd.append('mypdf',file);
$.ajax({
url: '/model/send', //here is also a problem, depends on your
data: fd, //backend language, it may looks like '/model/send.php'
dataType: 'text',
processData: false,
contentType: false,
type: 'POST',
success: function (response) {
alter('Exit to send request');
},
error: function (jqXHR) {
alter('Failure to send request');
}
});
and if you are using php on your backend , you could have a look on your data information:
echo $_FILES['mypdf'];

This code is for capturing Html page from screen and save as Pdf and send to back end api As blob
const filename = 'form.pdf';
const thisData = this;
this.printElement = document.getElementById('content');
html2canvas(this.printElement).then(canvas => {
this.pdfData = new jsPDF ('p', 'mm', 'a4');
this.imageHeight = canvas.height * 208 / canvas.width;
this.pdfData.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, 208, this.imageHeight);
this.pdfData.save(filename);
this.uploadFile(this.pdfData.output('blob'));
});
}
uploadFile(pdfFile: Blob) {
this.uploadService.uploadFile(pdfFile)
.subscribe(
(data: any) => {
if (data.responseCode === 200 ) {
//succesfully uploaded to back end server
}},
(error) => {
//error occured
}
)
}

Related

Write to file while stream downloading

How to write output of an octet-stream to a file while the stream is being downloaded ?
I receive the stream as a blob and then download it at the end of the stream, but how to receive the
stream and write to a file ?(something like a FileStream that takes a stream and writes to a file)
AJAX code below
$.ajax({
type: "post",
url: apiURL,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(String(strCustomData)),
xhrFields: {
responseType: "blob", // <-- can also be an arrayBuffer
onprogress: function(e) { // <-- get response body here, read its stream and save in file
// TODO
}
},
cache: false,
headers: { "RequestVerificationToken": get_CSRF_TOKEN() },
success: function (response, textStatus, request) {
const requestHeaders = request.getResponseHeader("Content-Disposition") || "";
const requestContentType = request.getResponseHeader("Content-Type") || "application/zip";
const strFileName = requestHeaders?.split(";")[1]?.split("=")[1] || "File_Not_Found.zip";
const blob = response;
const url = window.URL || window.webkitURL;
const urlLink = url.createObjectURL(blob);
// create Anchor element that holds the blob and then download it as a file
const elementAnchor = document.createElement("a");
elementAnchor.setAttribute("href", urlLink);
elementAnchor.setAttribute("download", strFileName);
// download the file
elementAnchor.click();
// dispose blob object and delete it from memory
url.revokeObjectURL(urlLink);
elementAnchor.remove();
},
error: function (xhr, ajaxOptions, thrownError) {
// More validation code...
console.error(String(xhr.statusText));
}
});
I am looking for something like the anchor download tag <a asp-page-handler="apiURL" download>Download</a> where it receives a stream and downloads its without using a blob.
I would have used the anchor tag, but I need some Javascript code to be executed alongside it.(Progress bar, some required custom info to display, ...etc.)
I tried using StreamSaver.js but could not make it work in the onprogress section of the AJAX request.(how to get the response.body.getReader() in onprogress event ?how to save stream to a file without waiting for the download to complete ?)
Using JQuery inside Razor pages with Asp.Net Core.

jQuery AJAX response coming as string blob

I am calling AWS S3 to retrieve images using AJAX call in jQuery 3.3.0 and instead of getting a blob object, I am receiving the response as "[object Blob]". Please let me know if I have to provide further details.
Please find the code below:
$.ajax({
url: "my_path/download_image.php",
data: {
name: "my_name"
},
cache: false,
xhrFields: {
responseType: 'blob'
},
success: function (data) {
console.log(data);
var image = new Image();
var url = window.URL || window.webkitURL;
self.DownloadStudentImages(students, index + 1);
image.src = url.createObjectURL(data);
self.SavePic(imageFilename);
},
error: function () {}
});
I have fixed the issue. Usually, AWS response from PHP is in string format unless it is encoded explicitly. So, I am sending base64 from PHP and in the javascript side, I am converting it to a byte array and thus into a blob which fixes the issue.

Save the circular crop image from Cropper

I'm using Cropper to crop the images in a circular shape from this example:
https://github.com/fengyuanchen/cropperjs/blob/master/examples/crop-a-round-image.html
Here is a fiddle: http://jsfiddle.net/7hsr98w4/7/
That's how the cropped image looks like:
<img src="data:image/png;base64,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">
Then I use Ajax to send that blob to PHP to upload that image:
document.getElementById('button').addEventListener('click', function(){
var imgurl = cropper.getCroppedCanvas().toDataURL();
cropper.getCroppedCanvas().toBlob(function (blob) {
var formData = new FormData();
formData.append('avatar', blob);
// Use `jQuery.ajax` method
$.ajax('upload.php', {
method: "POST",
data: formData,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log('Upload error');
}
});
});
});
This code could be found here:
https://github.com/fengyuanchen/cropperjs#getcroppedcanvasoptions
In upload.php:
print_r($_FILES);
if(isset($_FILES['avatar']) and !$_FILES['avatar']['error']){
file_put_contents("uploads/image.png", file_get_contents($_FILES['avatar']['tmp_name']));
}
exit();
That's the response from print_r($_FILES):
Array
(
[avatar] => Array
(
[name] => blob
[type] => image/png
[tmp_name] => C:\xampp\tmp\php2BDA.tmp
[error] => 0
[size] => 2135
)
)
When I console.log() blob, I get and Object:
Blob(2135) {size: 2135, type: "image/png"}
But when I view the image on the uploads folder, It's a rectangular image not circular.
Here is how it's previewed after cropping:
And that's how it's previewed on uploads folder:
Both images(previewed and saved) are 360x360.
How to save the cropped image in circular shape like how it's previewed after cropping?
You need to add rounding box css for .cropper-crop-box also
.cropper-crop-box, .cropper-view-box {
border-radius: 50%;
}
If you want circular view box you can use this
.cropper-view-box {
box-shadow: 0 0 0 1px #39f;
outline: 0;
}
UPDATE:
Sorry I misunderstood your question actually what you wanted was pretty straightforward
You already have getRoundedCanvas() which gets you the rounded version of crop, so just need to use it in your ajax call like
document.getElementById('button').addEventListener('click', function(){
var imgurl = cropper.getCroppedCanvas().toDataURL();
//only this line is changed
getRoundedCanvas(cropper.getCroppedCanvas()).toBlob(function (blob) {
var formData = new FormData();
formData.append('avatar', blob);
// Use `jQuery.ajax` method
$.ajax('upload.php', {
method: "POST",
data: formData,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log('Upload error');
}
});
});
});
I think that this function getroundedcanvas() doesn't exist with the jquery-cropper.js, if it was you, you have already done a great job with your function, I really needed it badly this is what I added and uploaded it with PHP.
case 'getCroppedCanvas':
if (result) {
// Upload cropped image to server if the browser supports `HTMLCanvasElement.toBlob`.
// The default value for the second parameter of `toBlob` is 'image/png', change it if necessary.
// Round
var roundedCanvas = getRoundedCanvas(result);
// Show
$('img.MyImage').attr('src',roundedCanvas.toDataURL());
var roundedBlob ;
roundedCanvas.toBlob((blob) => {
roundedBlob = blob;
});
result.toBlob((blob) => {
const formData = new FormData();
// Pass the image file name as the third parameter if necessary.
formData.append('UploadPhoto', blob, 'profil.png' );
formData.append('CircleBlob', roundedBlob, 'circle.png' );
$.ajax(document.location.pathname, {
method: 'POST',
data: formData,
processData: false,
contentType: false,
success(response) {
console.log(response);
console.log('Upload success');
$('#imgResizeModal').modal("hide");
},
error() {
console.log('Upload error');
},
});
}/*, 'image/png' */);
}
break;

How do you upload a single image with Dropzone.js?

Dropzone.js seems to be uploading images as multi-part form data. How do I get it to upload images in the same way an image upload would work with cURL or a binary image upload with Postman?
I'm getting a pre-signed URL for S3 from a server. The pre-singed URL allows an image upload, but not form fields:
var myDropzone = new Dropzone("#photo-dropzone");
myDropzone.options.autoProcessQueue = false;
myDropzone.options.autoDiscover = false;
myDropzone.options.method = "PUT";
myDropzone.on("addedfile", function ( file) {
console.log("Photo dropped: " + file.name );
console.log("Do presign URL: " + doPresignUrl);
$.post( doPresignUrl, { photoName: file.name, description: "Image of something" })
.done(function( data ) {
myDropzone.options.url = data.url
console.log(data.url);
myDropzone.processQueue();
});
});
If I use the returned URL with Postman and set the body to binary and attach the image, then the upload works fine. However, if the Dropzone library uses the same URL to upload the image to S3 then I get a 403 because S3 does not expect form fields.
Update:
An Ajax alternative works as below with a S3 signed url, but Dropzone.js does not seem willing to put the raw image data in the PUT message body.
$.ajax( {
url: data.url,
type: 'PUT',
data: file,
processData: false,
contentType: false,
headers: {'Content-Type': 'multipart/form-data'},
success: function(){
console.log( "File was uploaded" );
}
});
Set maxFiles to 1.
Dropzone.autoDiscover = false;
dzAllocationFiles = new Dropzone("div#file-container", {
url: "api.php?do=uploadFiles"
, autoDiscover: false
, maxFiles: 1
, autoQueue: true
, addRemoveLinks: true
, acceptedFiles: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
dzAllocationFiles.on("success", function (file, response) {
// Success Operations
});
dzAllocationFiles.on("maxfilesexceeded", function (file, response) {
allocationFileNames = [];
this.removeAllFiles();
this.addFile(file);
});
Add below options, then working.
myDropzone.options.sending = function(file, xhr) {
var _send = xhr.send;
xhr.send = function() {
_send.call(xhr, file);
}
}

Upload files to Dropbox using a Dropbox Core API in Javascript

I am working on a simple chrome-extension that needs to upload files to the user's dropbox folder. I am using the simple AJAX requests as mentioned below to upload files, however it works for files with extensions such as .txt, .json, .c, etc i.e. files whose mime type is of type text/plain or similar type but all other file types such as pdfs, image files etc get corrupted and produce blank contents. What am I missing in uploading the files the correct way.
function startUpload()
{
var folderPath = $(this).closest('tr').attr('path')+'/';
var file = $("#upload_file")[0].files[0];
if (!file){
alert ("No file selected to upload.");
return false;
}
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
uploadFile(folderPath+file.name,evt.target.result,file.size,file.type);
}
}
//function to upload file to folder
function uploadFile(filepath,data,contentLength,contentType){
var url = "https://api-content.dropbox.com/1/files_put/auto"+filepath;
var headers = {
Authorization: 'Bearer ' + getAccessToken(),
contentLength: contentLength,
};
var args = {
url: url,
headers: headers,
crossDomain: true,
crossOrigin: true,
type: 'PUT',
contentType: contentType,
data : data,
dataType: 'json',
success: function(data)
{
getMetadata(filepath.substring(0,filepath.lastIndexOf('/')),createFolderViews);
},
error: function(jqXHR)
{
console.log(jqXHR);
}
};
$.ajax(args);
}
I believe the issue is reader.readAsTextFile(file, "UTF-8"). If the file isn't a text file, this will misinterpret the contents. I think you want reader.readAsBinaryString or reader.readAsArrayBuffer. (I haven't tested it myself.)
EDIT
After testing this myself, I found that readAsArrayBuffer is what you need, but you also need to add processData: false as an option to $.ajax to prevent jQuery from trying to convert the data to fields in a form submission.
Also be sure to use dataType: 'json' to properly parse the response from the server.

Categories

Resources