How to save Canvas element to png file with php and ajax? - javascript

I want to save a html canvas element as an image using php and jquery ajax.
Here is my code for ajax.
var front_image=canvas.toDataURL("image/png");
//front image is a base_64 string
$.ajax({
url:base_url+'tabs/profile/save_front_image',
type:'POST',
data:'front_image='+front_image,
success:function(response){
}
});
I m just doing echo in php echo $_POST['front_image'] so request and response are same.
When i use this code before ajax it loads image to new tab of browser
var w = window.open('about:blank', 'image from canvas');
w.document.write("<img src='" + frame_image + "' alt='from canvas'/>");
but when i put the same code on ajax response as bellow it doesn't work. Only a blank tab opens in browser. So i m not being able to save image as file.
var w = window.open('about:blank', 'image from canvas');
w.document.write("<img src='" + response + "' alt='from canvas'/>");
I compared string length of frame_image and response also. They are same. I m not sure why image is not loading in response. Please suggest me the answer thanks.

// soon you can use front_image=canvas.toBlob("image/png")
// construct a blob
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
// make an actually file from the base64 so we can send binary data
var blob = b64toBlob(front_image.split(",")[1], "image/png")
var fd = new FormData();
fd.append("file", blob, "filename.png");
$.ajax({
url: 'http://example.com/script.php',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data){
alert(data);
}
});
// The saving
<?php
$uploads_dir = '/uploads';
foreach ($_FILES["file"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["file"]["tmp_name"][$key];
$name = $_FILES["file"]["name"][$key];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
?>

Related

ie11 Downloading Base64 documents

I have tried pretty much everything at this point and I cannot get anything to work in ie.
I need ie to download base64 documents from an attachment panel. I have no access to the server side code or database. The images cannot be stored in a folder to be pulled up, they need to be presented this way.
I have tried using a plain link and sticking the base64 sting in there and it just opens up a new blank window.
<a target="_blank" download class="btn btn-primary downloadAttachment" href="' + blobUrl + '" >Download</a>
I have tried turning the url into a blob and opening the blob and that resulted in the browser not doing anything.
function base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = base64Data;
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
I am completely and totally stuck. I have tried everything from google and on here.
My two latest attempts here
https://jsfiddle.net/pqhdce2L/
http://jsfiddle.net/VB59f/464/
Some time ago I've coined this function to make ("offer/initialize") a download of an xlsx or csv content accepting both a Blob or a base64 string:
// Initializes a file download of a provided content
//
// Not usable outside browser (depends on window & document)
//
// #param {Blob|base64} cont File content as blob or base64 string
// #param {string} ftype File type (extension)
// #param {string} [fname='export.' + ftype] File name
// #param {string} [mime='application/zip'] File mime type
// #returns {void}
function makeFileDownload(cont, ftype, fname, mime) {
if (!fname) fname = 'export.' + ftype;
if (!mime) mime = ftype === 'csv' ? 'text/csv' : 'application/zip'; // or 'application/vnd.ms-excel'
if (Object.prototype.toString.call(cont) === '[object Blob]'
&& window.navigator && window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(cont, fname);
}
else {
var downloadLink = document.createElement('a');
downloadLink.download = fname;
downloadLink.href = typeof cont === 'string'
? 'data:' + mime + ';base64,' + cont
: window.URL.createObjectURL(cont);
downloadLink.onclick = function(e) { document.body.removeChild(e.target); };
downloadLink.style.display = 'none';
document.body.appendChild(downloadLink);
downloadLink.click();
}
};
This should be able to accept both Blob and base64 string - you should get the idea how it's being done for either a Blob and a base64 string from the if/else block.
If passing it base64 string is problematic just convert it to a Blob first (as suggested for example in this SO question, this answer is specifically aimed at IE11). Adjust the mime defaults according to your expected usage.
I suppose you already have the content (Blob/base64), keep your original link (which I suppose is to be clicked by an user) a plain link or rather a button (i.e. without the download/href attributes), attach it a click event handler where you'll call the function and it should initialize the download for you:
document.querySelector('#originalLink').addEventListener('click', function () {
makeFileDownload(content, extension, filename, mimetype);
});
If you are trying to generate blob URL in IE, it will not work.
We have to download the file to local by using below code:
function printPdf(id) {
$.ajax({
url: 'url',
type: 'POST',
data: { 'ID': id },
success: function (result) {
var blob = pdfBlobConvesion(result.PdfUrl, 'application/pdf');
var isIE = /*#cc_on!#*/false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
if (isIE || isEdge) {
window.navigator.msSaveOrOpenBlob(blob, "ProviderOfficePDF.pdf");
}
else {
var blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank");
}
}
});
}
function pdfBlobConvesion(b64Data, contentType) {
contentType = contentType || '';
var sliceSize = 512;
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
var byteCharacters = window.atob(b64Data);
var byteArrays = [];
for ( var offset = 0; offset < byteCharacters.length; offset = offset + sliceSize ) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
IE, in classic fashion, requires you to use a proprietary method for "saving" a blob.
msSaveBlob or msSaveOrOpenBlob is what you're looking for.
Instead of adding it as the href, add an onclick handler to your a tag and call navigator.msSaveBlob(blob, "Sample Name");
Additionally if you need to support other browsers you'll need some other code to support those browsers.
For example:
var content = new Blob(["Hello world!"], { type: 'text/plain' });
var btn = document.getElementById('btn');
if (navigator.msSaveBlob) {
btn.onclick = download;
} else {
btn.href = URL.createObjectURL(content);
btn.download = true;
}
function download() {
if (navigator.msSaveBlob) {
navigator.msSaveBlob(content, "sample.txt");
}
}
<a id="btn" href="#">Download the text!</a>
var data = item;
var fileName = name;
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE
workaround
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {type: 'application/octet-stream'});
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
else if( agent.indexOf('firefox') > -1)
{
console.log(extention,'item111')
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
//var FileSaver = require('file-saver');
var blob = new Blob([byteArray], {type: "application/octet-stream"});
saveAs(blob, fileName);
}
else{
this.fileDownload='data:application/octet-stream;base64,'+item;
var link = document.createElement("a");
const fileName=name;
link.href = this.fileDownload;
link.download=fileName;
link.click();
}
}

How shall I read out data from a binary Excel from node.js REST API file and display it in HTML using Angularjs

I'm getting binary excel(.xls) data from node.js REST API, now I need to consume this service in Angular controller and convert this binary excel(.xls) file and preview the Excel in my project directly without downloading.
My code is
$scope.exportToExcel = function () {
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
var contentType = 'binary/octet-stream';
var b64Data = data;
var convert = b64toBlob(b64Data, contentType);
// var blob = URL.createObjectURL(convert);
console.log("DOWNLOAD: " + URL.createObjectURL(convert))
saveAs(convert, "Report.xls");
}
On Click action this code runs and download the binary data as excel file, but instead of downloading I need to directly display it in browser, I'm using Angularjs
Please guide me in this. Thanks

Error when printing PDF file in AngularJS

I am trying to print a PDF file generated through reportViewer in my Web API, but the browser shows an error when tries to open the PDF file.
This is the code inside the controller in my Web API:
// ...generate candidatosDataSet
LocalReport relatorio = new LocalReport();
string rootPath = HttpRuntime.AppDomainAppPath;
relatorio.ReportPath = rootPath + #"\Reports\Report.rdlc";
relatorio.DataSources.Add(new ReportDataSource("Candidatos", candidatosDataSet));
relatorio.Refresh();
byte[] relatorioBytes = ExportUtils.GerarArquivoPDF(relatorio);
response = Request.CreateResponse(HttpStatusCode.OK, relatorioBytes);
response.Content.Headers.ContentDisposition = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse("attachment; filename=relatorio.pdf");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
This is how I am generating PDF File through reportViewer
public static byte[] GerarArquivoPDF(LocalReport relatorio)
{
String reportType = "PDF";
String mimeType;
String encoding;
String fileNameExtension;
String deviceInfo;
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
deviceInfo = "<DeviceInfo>" + " <OutputFormat>" + reportType + "</OutputFormat>" + "</DeviceInfo>";
renderedBytes = relatorio.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
return renderedBytes;
}
Here is my AngularJS service method:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetRelatorio',
{
params: { candidatoId: candidatoId },
responseType: 'arraybuffer'
});
}
And this is the code that I am using to print the file on the AngularJS controller:
function imprimirTermoConfirmacaoCandidatura(id) {
CandidatoAPIService.obterTermoConfirmacaoCandidatura(id)
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = new Blob([response.data], {
type: contentType
});
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
The response from Web API was comming as string, with double quotes in beginning and in the end of the response, so the PDF File could not be rendered correctly. Also I converted the response from server to base64, by this method:
function b64toBlob(b64Data, contentType) {
var sliceSize = 512;
b64Data = b64Data.replace(/"/g, '');
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
var byteCharacters = window.atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
And changed the method on AngularJS controller to convert the response do base64:
function imprimirTermoAutorizacaoUsoImagem() {
CandidatoAPIService.obterTermoAutorizacaoUsoImagem()
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = UtilsService.b64toBlob(response.data, "application/pdf");
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
And removed the responseType on the AngularJS service:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetObterTermoConfirmacaoCandidatura',
{
params: { candidatoId: candidatoId }
});
}

Javascript image from base64 string

an api give send me base64 string that there is an image.
I have a function that traslate this string to blob storage.
function b64toPhoto(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
//var byteCharacters = atob(b64Data);
var byteCharacters = atob(b64Data.replace(/^data:image\/(png|jpg);base64,/, ''));
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
When I convert my string with atob(b64Data), I have this error:
Error failed to execute 'atob' on 'Window': the string to be decoded is not correctly encoded.
My encoded string start in this way:
/9j/4AAQSkZJRgABAgAAAQABAAD/7QCuUGhvdG9zaG9wIDMuMAA4Qk....
How I can decode this in javascript? I try my string with online converter (from base64 to image) and work fine.
Thanks
You can simply use the string to display image
var image = new Image();
image.src = '<string received>...';
document.body.appendChild(image);
you can try this:(you can see the code works here)
javascript file:
function getTextToDecode () {
//get the encoded string
var valuToDecode = document.getElementById("userCode").value;
//this is just for making the decoded image downloadable
var linkImg = valuToDecode.concat('" alt="Red dot" download="ganixo-file.png"> click here to download your img </a>');
document.getElementById("codedImg").innerHTML= '<a href="data:image/jpeg;base64,'.concat(linkImg);
if (valuToDecode == "") {
alert("text area is empty ! try again..");
}else{
//this is the answer for your question
//check if there is any errors
if(!atob(valuToDecode))
{
alert("bad format! try again..")
}else
{
//decode the encoded string
var decodedString = atob(valuToDecode);
//make the image downloadable
document.getElementById("decodeResult").value = decodedString;
}
}
}

Return base64 String of a File as a response using ASP.NET httpHandler inresponse to AJAX Request

I want to download multiple types of files using AJAX.
I decided to generate a get requests with file name as query string using AJAX and get the response as base64 string and then convert it to blob object and download/save it using hyperlink a tag along with download attribute.
Kindly help me, how to use the optimized way/code to convert file to base64 string and then revert the base64 string to blob?
ASP.Net httpHandler code is here:
Imports System
Imports System.Web
Imports System.IO
Public Class FileDownload : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim Request As HttpRequest = context.Request
Dim Response As HttpResponse = context.Response
Dim serverFile As String = Request.QueryString("filename")
Dim filePath As String = String.Empty
filePath = context.Server.MapPath("~") & "\" & serverFile
Dim file As New System.IO.FileInfo(filePath)
Try
If (file.Exists) Then
Response.Clear()
Response.ClearContent()
Using reader As New FileStream(filePath, FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Dim buffer As Byte() = New Byte(reader.Length - 1) {}
reader.Read(buffer, 0, CInt(reader.Length))
Response.Write(Convert.ToBase64String(buffer))
End Using
Response.Flush()
Response.End()
Else
Response.Write("File Not Found!")
Response.StatusCode = 500
End If
Catch ex As Exception
Response.Write(ex.ToString)
Response.StatusCode = 500
context.ApplicationInstance.CompleteRequest()
End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Javascript function called with httphadler's application path as url and client side file name as filename
function downloadFileByAjax(filename, url) {
$.ajax({
type: 'GET',
url: url,
responseType: 'arraybuffer',
downloadid: filename,
success: function (result, status, xhr) {
var octetStreamMime = 'application/octet-stream';
var filename = this.downloadid;
var contentType = xhr.getResponseHeader('content-type') || octetStreamMime;
var a = document.createElement('a');
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (urlCreator && window.Blob && ('download' in a) && window.atob) {
var blob = base64ToBlob(result, contentType);
var url = window.URL.createObjectURL(blob);
a.setAttribute('href', url);
a.setAttribute("download", filename);
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(event);
//window.URL.revokeObjectURL(url);
}
},
error: function (xhr, msg, error) {
//console.log(xhr, msg, error);
//console.log(xhr.responseText);
console.log(msg);
},
complete: function (xhr, status) {
//console.log('completed');
}
});
}
function base64ToBlob(base64, mimetype, slicesize) {
if (!window.atob || !window.Uint8Array) {
console.log('The current browser doesnot have the atob function. Cannot continue');
return null;
}
mimetype = mimetype || '';
slicesize = slicesize || 512;
var bytechars = atob(base64);
var bytearrays = [];
for (var offset = 0; offset < bytechars.length; offset += slicesize) {
var slice = bytechars.slice(offset, offset + slicesize);
var bytenums = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
bytenums[i] = slice.charCodeAt(i);
}
var bytearray = new Uint8Array(bytenums);
bytearrays[bytearrays.length] = bytearray;
}
return new Blob(bytearrays, { type: mimetype });
}
To convert a file to base64 string use the following code
string data;
using (FileStream fs = new FileStream(dir + fileName, FileMode.Open, FileAccess.Read)) {
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
data = Convert.ToBase64String(buffer);
fs.Close();
}
return data;
In the success function of the ajax call convert the string to blob using the following code
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = null;
blob = new Blob([byteArray], { type: 'text/plain' });
blob = new Blob([byteArray], { type: 'application/pdf;base64' });
var blobUrl = URL.createObjectURL(blob);
Depending upon the file format you can specify the type attribute for the blob and then assign the blobUrl as the source to your anchor tag

Categories