JavaScript Canvas Download - javascript

I have a problem downloading my drawing from a canvas. This is my code:
function downloadCanvas(link, canvasId, filename) {
link.href = document.getElementById(canvasId).toDataURL();
const le = link.href;
console.log(le);
le.download = filename;
};
download.addEventListener('mousedown', function() {
downloadCanvas(this, 'draw', 'Drawing.jpeg');
}, false);
The console show the value of le, which is the link to download, but the file isn't downloaded... What is wrong here? I'm a beginner.

The issue you have is you're attempting to download a link location, whereas you simply need to be downloading the link file.
To fix this, you should change the const le = link.href; to const le = link;. However, you might as well just get rid of the const le and change le.download to link.download.
Hope that helps!
Edit:
Here's a cleaned up version of the code:
function downloadCanvas(link, canvasId, filename) {
link.href = document.getElementById(canvasId).toDataURL();
link.download = filename;
};
download.addEventListener('mousedown', function() {
downloadCanvas(this, 'draw', 'Drawing.jpeg');
}, false);

Related

converting from html to png image on initial button click

I am converting part of the html elements into canvas and converting that into png image. It is working fine but the problem is at the first click it is not converting the html to convas and canvas to png.
//HTML To Image on button click
$("#btn-Convert-Html2Image").on('click', function () {
html2canvas(element, {
onrendered: function (canvas) {
getCanvas = canvas;
}
});
setTimeout(function() {
var imgageData = getCanvas.toDataURL("image/png");
var newData = imgageData.replace(/^data:image\/png/, "data:application/octet-stream");
$("#btn-Convert-Html2Image").attr("download", "your_pic_name.png").attr("href", newData);
},400)
});
Is that anything done wrong. Please see the fiddle link
At first click you are binding png dataURL to #btn-Convert-Html2Image anchor and when 2nd time you click on this link already bound data is downloaded you can use this approach to overcome this issue.
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
$("#btn-Convert-Html2Image").on('click', function () {
html2canvas(element, {
onrendered: function (canvas) {
var imgageData = canvas.toDataURL("image/png");
var newData = imgageData.replace(/^data:image\/png/, "data:application/octet-stream");
downloadURI(newData,"your_pic_name.png");
}
});
});
JSFiddle link
Good news: You make everthing right!
The last line of code says : Set the atribute of the download button to your image. Thast good but to late. You have already clicked the button. So wehn you click the button again the image from the last run will be downloaded and a new one will be generated and linked to the button.
You simply have to force the download AFTER you have generated the image. For example by forcing a URI download ...

Downloading a PDF using JavaScript that is Cross Browser Compatible

I can download a PDF using AngularJS in Chrome, but this doesn't appear to work in the latest FireFox, Internet Explorer 11 or Edge (assuming it doesn't work for IE10 either), and I know a shim is needed for IE9. Don't know if this the best shim for this if anyone has an opinion, but currently it doesn't seem to work. I tried it with a response type of blob and arraybuffer just in case that made a difference, and it doesn't.
All this counters what caniuse indicates about using the Blob URLs. Anyone have this working in IE9 and up, and the last couple versions of FF, and can point out what I'm doing wrong?
$http({
url: '/api/v1/download',
method: 'GET',
responseType: 'blob' // or 'arraybuffer'
}).then(function (response) {
// Use the Blob object to create an object URL to download the file
var url = URL.createObjectURL(response.data);
// var url = URL.createObjectURL(new Blob([response], {type: 'application/pdf'})); // arraybuffer version
// Create an anchor to perform download, but don't append to the DOM
anchor.href = downloadUrl;
anchor.download = filename;
anchor.target = '_blank';
anchor.click();
URL.revokeObjectURL(downloadUrl);
anchor = null;
}).catch(function (reason) {
console.log('FAIL', reason);
});
UPDATE
Currently the best (only) answer works for IE10, 11, Edge, FF, and continues to work with Chrome. IE9 won't work using this solution if anyone has another polyfill/shim/other/etc, and Safari doesn't support the download attribute so the solution in the chosen answer doesn't work in an SPA since it just redirects the current page so in both these cases I've just left TODO stubs.
This is an update to the posted answer with more information added in comments for anyone to use or hopefully add to so IE9 and Safari work as expected:
function performDownload(blob, filename) {
// IE9 has no API for handling downloads using Blob objects, and doesn't support the download attribute
if(isIE() == 9) {
// TODO: polyfill/shim/other... change response type to?
}
// Only works for IE10 and up, including Edge
else if (typeof window.navigator.msSaveBlob !== 'undefined') {
// Provides a prompt to save the file to a location of users choice
window.navigator.msSaveBlob(blob, filename);
}
// Browsers that adhere to current standards can implement downloads
// using the Blob object with the download anchor attribute
// ---
// NOTE: Edge 13+ is compliant with both these standards, but Edge 12
// does not support the download anchor attribute so all versions
// have been grouped to use the propriety `msSaveBlob` method
else {
// Use the Blob object to create an object URL to download the file
var URL = window.URL;
var downloadUrl = URL.createObjectURL(blob);
var anchor = document.createElement('a');
if(angular.isDefined(anchor.download)) {
anchor.href = downloadUrl;
anchor.download = filename;
anchor.target = '_blank';
document.body.appendChild(anchor); // Required by Firefox
anchor.click();
// Release the existing object URL, and the anchor
$timeout(function () {
URL.revokeObjectURL(downloadUrl);
document.body.removeChild(anchor);
anchor = null;
}, 100);
}
else {
// TODO: Safari does not support the download anchor attribute...
}
}
}
I've used this with success in both IE11 and Chrome:
function saveBlob(response, contentType, filename) {
let blob = new Blob([response.arrayBuffer()], { type: contentType });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround
window.navigator.msSaveBlob(blob, filename);
} else {
let URL = window.URL;
let downloadUrl = URL.createObjectURL(blob);
if (filename) {
let a = document.createElement('a');
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
// cleanup
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100);
}
}

Firefox a.click won't fire without a breakpoint

I'm working on a project where we have an AJAX call which responds with a blob containing an excel file. I want the code to open the file as a download when I get the response. Here is the callback:
var blob = new Blob([response.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
var header = response.headers("Content-Disposition");
a.download = header.substring(header.indexOf("filename=") + "filename=".length);
a.href = objectUrl;
document.body.appendChild(a);
console.debug("Clicking a tag");
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(objectUrl);
This code works fine in chrome but in firefox nothing happens when a.click() fires. The debug statement prints so I know that the callback is happening. Also, for some reason, if I put a breakpoint on a.click() it works perfectly.
Can someone explain why the click only works in debug mode?
Firefox has a couple of safeguards or just odd behaviors around things like this. I don't know the derivation, but yielding back to the browser for a moment before doing the click usually clears it up:
// ...
a.href = objectUrl;
document.body.appendChild(a);
setTimeout(function() {
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(objectUrl);
}, 0);
// ...
Note that code following the setTimeout will run before the content of the setTimeout does.
You might even need two:
// ...
a.href = objectUrl;
document.body.appendChild(a);
setTimeout(function() {
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(objectUrl);
}, 0);
}, 0);
// ...

Generate a download from client side javascript data

I've this code to generate a download from javascript but I can't/don't know how to make it work on mobile devices.
$('#export').on("click", function (e) {
var Datos = {
"imagen": "asdfASDF123",
"puntos": [{"a":"1"}, {"b":"2"}, {"c":"3"}]
};
stringy = JSON.stringify(Datos);
var blob = new Blob([stringy], {
type: "text/json"
});
var uri = URL.createObjectURL(blob);
var link = document.createElement("a");
link.download = 'datos.json';
link.href = uri;
document.body.appendChild(link);
fireEvent(link, "click");
document.body.removeChild(link);
delete link;
});
Is there something bad in this code? or is there another method to generate a download from javascript that works on mobile devices?

Generate an image of a div and Save as

I'd like to create an input button "Save image" that :
take a screen shot of a div
ask to "Save as" on the user's computer
I've found how to create a screen of a dive using html2canvas and to open it in a new tab, it works perfectly :
function printDiv2(div)
{
html2canvas((div), {
onrendered: function(canvas) {
var img = canvas.toDataURL();
window.open(img);
}
});
}
But for thee Save as part, is a kind of the tough part... I've found interesting topics, as I'm new in JS (and object) coding, I'm a little bit confused... I think I'll have to use the FileSaver.js and to create a new blob
http://eligrey.com/blog/post/saving-generated-files-on-the-client-side/
But I don't get how to implement the saveAs in my html2canvas, how to cast properly a new blob...
function printDiv2(div)
{
html2canvas((div), {
onrendered: function(canvas) {
var img = canvas.toDataURL();
window.open(img);
var blob = new Blob(img, {type: "image/jpeg"});
var filesaver = saveAs(blob, "my image.png");
}
});
}
Also I tried to do something with this, by extracting the base64 generated URL, but it's too complicated for me to understand everyting :
http://bl.ocks.org/nolanlawson/0eac306e4dac2114c752
But someone give me a few tips and help me please ?
You could do this approach:
//Creating dynamic link that automatically click
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
link.click();
//after creating link you should delete dynamic link
//clearDynamicLink(link);
}
//Your modified code.
function printToFile(div) {
html2canvas(div, {
onrendered: function (canvas) {
var myImage = canvas.toDataURL("image/png");
//create your own dialog with warning before saving file
//beforeDownloadReadMessage();
//Then download file
downloadURI("data:" + myImage, "yourImage.png");
}
});
}
Here is the final code, if it can helps you :
function PrintDiv(div)
{
html2canvas((div), {
onrendered: function(canvas) {
var myImage = canvas.toDataURL();
downloadURI(myImage, "MaSimulation.png");
}
});
}
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
//after creating link you should delete dynamic link
//clearDynamicLink(link);
}
Have you looked at
http://eligrey.com/demos/FileSaver.js/
Looks like it does what you need
This works fine for me.
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
clearDynamicLink(link);
}
function DownloadAsImage() {
var element = $("#table-card")[0];
html2canvas(element).then(function (canvas) {
var myImage = canvas.toDataURL();
downloadURI(myImage, "cartao-virtual.png");
});
}
Nowadays html2canvas has changed to javascript promise. So the updated code should be:
function PrintDiv(div)
{
html2canvas(div).then(canvas => {
var myImage = canvas.toDataURL();
downloadURI(myImage, "MaSimulation.png");
});
}
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
//after creating link you should delete dynamic link
//clearDynamicLink(link);
}

Categories