Download html2canvas image to specific file path - javascript

export default class Thumbnail {
getThumbnail(canvas) {
html2canvas(canvas)
.then((canvas) => {
this.saveAs(canvas, 'thumbnail.png');
}).catch(function(err) {
console.log(err);
})
}
saveAs(canvas, filename) {
let link = document.createElement('a');
if (typeof link.download === 'string') {
link.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
window.open(canvas);
}
}
}
I have created a module Thumbnail taking canvas tag as its parameter to take a screen capture of the designated area when called from the html script tag (so whenever I refresh the local page, it calls the module)
As far as I know, the html2canvas saves the image to the download folder as its default. If I would like to save an image to a specific file path what should I do?
For example, if I would like to save the image into a folder with a file path of ./Desktop/Project/Assets/Thumbnail, is there any way to add such command inside the code?

No web browser will permit this.
You as the page author have zero control over where the file is saved. This is as much for security and privacy as it is about user preferences.
This applies to all downloads, not just files created by the html2canvas package.
If you're building a tool that only you will use (and it sounds like you are), you may be able to accomplish the same result by writing a non-web shell script that monitors your Downloads directory and moves these files to the special location when they appear.
For that to work, you'd want to give all the screenshots names that follow a pattern you can easily recognize with your shell script.

Related

Download image from a third-party server button

In any browser, if you saw an image, you can right-click on it and click "save as" to download it.
I'm trying to make a button to download an image
The download button should download the image above, the barcode.
I am using react, not sure if this has something to do with the answers.
I read that you can use the <a/> tag with the download attribute, however, I'm on Firefox, and it's redirecting me to a page where the barcode image is hosted, and it's not opening the download window instead:
The code is pretty simple, it look as follows:
<a href='https://barcode.tec-it.com/barcode.ashx?data=${product.barcode}&code=&multiplebarcodes=true&backcolor=%23ffffff&quietzone=10&quietunit=Px&size=Small' download>click me</a>
From the MDN docs:
download only works for same-origin URLs, or the blob: and data:
schemes.
I want to implement this, how can I do it?
I'm not the owner of the server where the image is hosted.
Can we do that in 2023?
The other questions are mixing between local images and images hosted on other servers.
So I thought I could create this thread for people interested only in images on third party servers. - so we are all front-end here, no back-end related stuff.
I think your question refers to this old question.
You need something on the server to send a Content-Disposition header to set the file as an attachment so the browser will not try to handle the file internally.
Please see:
href image link download on click
It only works on the same website, not an external link. Try an image of the same website. Ex: <a href="images/detailed-product.png" download>click</a>
You'll need to proxy the request to avoid CORS issues. As the article states it's better to deploy your own proxy, but you can test with a free one, eg: https://codetabs.com/cors-proxy/cors-proxy.html
StackBlitz updated example:
const downloadButton = document.querySelector('button');
downloadButton.onclick = () => {
console.log('download button clicked');
downloadImage(
'https://api.codetabs.com/v1/proxy?quest=https://barcode.tec-it.com/barcode.ashx?data=${product.barcode}&code=&multiplebarcodes=true&backcolor=%23ffffff&quietzone=10&quietunit=Px&size=Small'
);
};
async function downloadImage(imageSrc) {
try {
const image = await fetch(imageSrc);
const imageBlob = await image.blob();
const imageURL = URL.createObjectURL(imageBlob);
const link = document.createElement('a');
link.href = imageURL;
link.download = 'image.jpg';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.log(error);
}
}
<button>Download image</button>
To do that, you can utilize the createObjectURL static method from URL to create download link for the image. Then, we create temporary <a> in a variable to open that link programmatically.
async function downloadImage(imageSrc) {
const image = await fetch(imageSrc)
const imageBlob = await image.blob()
const imageURL = URL.createObjectURL(imageBlob)
const link = document.createElement('a')
link.href = imageURL
link.download = 'myimage.jpg'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}

How to change the extension name of a file before downloading?

I have a video file hosted which looks like this:
https://cdn.shopify.com/s/files/1/0664/3037/0044/files/video
Right now, the video file has no extension at all. Using Javascript, how can I download the file with .mp4 extension. I need a way to change its filename to [filename].mp4 and then download.
I tried the following but it downloads the file without the extension.
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;
}
downloadURI("https://cdn.shopify.com/s/files/1/0664/3037/0044/files/video", "video.mp4");
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download
download only works for same-origin URLs, or the blob: and data:
schemes. If the Content-Disposition header has different information
from the download attribute, resulting behavior may differ:
If the header specifies a filename, it takes priority over a filename
specified in the download attribute. If the header specifies a
disposition of inline, Chrome and Firefox prioritize the attribute
and treat it as a download. Old Firefox versions (before 82)
prioritize the header and will display the content inline.
I tried your code on a different origin and it wouldn't download but simply redirect to the URL, also it doesn't send Content-Disposition, so it looks like since you're testing this on a different origin, it just redirects to the file link, discarding download because it's on a different origin, and your browser is configured to download it. My browser is configured to autoplay videos.
However, I see the URL you provided has CORS *, meaning any origin can access it. So, an alternative you can do is, download the file, and create a blob, then send download to browser.
function downloadURI(uri, name) {
fetch(uri).then((response) => response.blob())
.then((blobresp) => {
var blob = new Blob([blobresp], {type: "octet/stream"});
var url = window.URL.createObjectURL(blob);
var link = document.createElement("a");
link.download = name;
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
})
}
downloadURI("https://cdn.shopify.com/s/files/1/0664/3037/0044/files/video", "video.mp4");
const myRenamedFile = new File([myFile], 'my-file-final-1-really.txt');
Taken from this website which may be a better at explaining than me:
https://pqina.nl/blog/rename-a-file-with-javascript/
alternatively, there seems to be lots of APIs or Node JS that can manage this. This will allow you to rename the file after it's been downloaded and is now a local file.

Download multiple files via Axios and .zip them

I am trying to expose a .zip in VueJS containing multiple files that are stored in a remote server.
I have tried at least with just one .csv file: the download works, but opening the archive fails because the .zip is recognised as invalid.
What I have tried to do is, this following this previous issue:
try {
const response = await axios.get(download_url, {
responseType:'blob'
});
const url = window.URL.createObjectURL(new Blob([response.data));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "filename.zip");
document.body.appendChild(link);
link.click();
} catch (error) {
console.log(error);
}
That allows me to download the .zip, but again, it is invalid and I cannot open it.
Then, I would like to be able to do it with multiple "download_urls", i.e. with multiple files in the same .zip, but for now I would be happy to succeed at least with one file!
Thank you in advance with your help.
Let the link () be directly what you are getting from axios (axios.get(url))
To download multiple file in one zip you could let the server pack them and provide public link to download (we can elaborate on this if you need to)
Again use that public link from the server to download the zip
Use download_url and put it in a

<a> element does not recognize the file extension automatically when downloading a file

I'm currently developing an application where the user clicks on an element, that element calls a JS function and the function handles a file download.
The files are reports generated dynamically by Devexpress XtraReports module, converted to Base64 and then sent back to the client side. When the client receives the Base64 string, the JS function creates an <a> element, sets the href attribute to data:application/pdf;base64,JVBERi0xLjQNCiWio[...] and simulates a click with the click() event.
Here's the piece of JS code that handles the file download:
let downloadLink;
try {
downloadLink = executionId ? await getLinkPdfBase64(executionId) : false;
} catch (error) {
downloadLink = false;
console.log(error);
}
if (downloadLink) {
const aElement = document.createElement("a");
downloadLink = "data:application/pdf;base64," + downloadLink;
aElement.setAttribute("download", currentReportData.LayoutName);
aElement.setAttribute("href", downloadLink);
aElement.click();
aElement.remove();
} else {
DevExpress.ui.dialog.alert( //Ignore this, it's a Devexpress component
"Your report could not be generated",
"Alert"
);
}
The problem is:
When I generate a report with custom parameter types, Devexpress generates it correctly (the Base64, if converted to string, is visibly correctly formed) but the browser (Google Chrome) downloads the file with the extension ".0".
If the report has normal Devexpress parameters (like Strings, Int32, Guids, etc)) the file is downloaded with the correct ".pdf" extension.
Here's a picture of a correctly downloaded PDF and a ".0" extension file:
Could it be the JS function the cause or the solution to the problem? If not, almost for sure there will be something wrong with the report generator (Devexpress).
NB: If I manually change the ".0" extension to ".pdf" the file opens and it is displayed / formed correctly.
Turns out I ended up solving it just by adding the file extension ".pdf" in the download attribute, so when the browser can't recognize it, you are already specifying which one it is:
aElement.setAttribute("download", currentReportData.LayoutName + ".pdf");

Let the User download the CSS file for iframe element

I am using two following JS functions to do the following steps:
Get iFrame html content generated via user interaction into a string
THEN Get the CSS stylesheet contained on my server named "myStylesheet.css" into a string
THEN Download those files to the reguesting user
var iframe = document.getElementById('frame');
function downloadFile(filename, text) {
var pom = document.createElement('a');
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
if (document.createEvent) {
var event = document.createEvent('MouseEvents');
event.initEvent('click', true, true);
pom.dispatchEvent(event);
}
else {
pom.click();
}
//example : downloadFile("hello.txt", "Hello World!") or for custom name filedownloadFile(myPageName +'.html', iFrameContent)
}
function publishWebsite(){
var htmlCodeForFrame = document.getElementById('frame').contentWindow.document.body.innerHTML;
var ccsCodeForFrame = "";
downloadFile("myWebsite.html", htmlCodeForFrame); //save html of frame into a file and download it to user
downloadFile("myStylesheet.css", ccsCodeForFrame); //save css of frame into a file and download it to user
}
My problem lies in turning a CSS stylesheet into a variable then download it (I want to stick with my download function for clarity because this is a Team Project and it's used in many other places.) to user. I wish this to be done in Javascript.
For modern browsers you could use the download-tag
Download
N.B: the file name is not required
(see browser support)
One other (rather nasty) trick is to create an ajax request with an invalid MIME-type, this prompts the browser to download the file since it can't render the view. Or you could use the application/octet-stream MIME-type.
I found myself using the following after some tinkering:
<iframe id="cssFrame" src="myStylesheet.css" style="display: none;"></iframe>
With conjunction of my code from the first post, I saved the content of the iframe to a string and saved the string in a file with .css extension. Works good.

Categories