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

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.

Related

How to download files from google cloud storage to user pc (React)

I have files on google cloud storage and i want to add a button so that users can download those files to their pc. I tried the usual:
Download
But it only opens the image file in the same tab.
Everything running on the front end of the app by the way.
Since you already have the download URL of the File stored in Cloud Storage, the following function will do the trick:
triggerBrowserDownload(url) {
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
link.setAttribute('target', 'new');
document.body.appendChild(link);
link.click();
}
And you can call it with
<a onclick=triggerBrowserDownload("imageUrlHere")>Download</a>
Or, better, by adding a listener:
HTML
<a id="urlLink" url="imageUrlHere">Try it</a>
JavaScript
document.getElementById("urlLink").addEventListener('click', triggerBrowserDownload);
triggerBrowserDownload(evt) {
const link = document.createElement('a');
link.href = evt.target.attributes.value.url;
link.setAttribute('download', fileName);
link.setAttribute('target', 'new');
document.body.appendChild(link);
link.click();
}
An alternative to using HTML attributes would be to set the Content-Disposition header to attachment; filename="file.ext" so you can use the downloadURL so whenever the URL is opened in new tab, it'll be downloaded. This can be set in the metadata when uploading the file or you can use updateMetadata() function to add it for existing files.
const storageRef = ref(storage, 'image.png')
// Adding metadata while uploading files
await uploadBytes(
storageRef,
file,
{
contentDisposition: `attachment; filename="${file.name}"`,
}
)
// Updating metadata for existing files
await updateMetadata(storageRef, {
contentDisposition: 'attachment; filename="image.png"',
})
You just need to redirect the user to a new tab. If you don't specify the filename, the browser will prompt user to enter one.
Download

Download html2canvas image to specific file path

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.

JavaScript can't download images programmatically (getting 403)

In my website I've a button that whenever user clicks on it downloads him a random image, here is the code to download an image:
const downloadImg = (src) => {
const imgName = src.replace(/^.*[\\\/]/, '');
var a = document.createElement('a');
a.href = src;
a.download = imgName;
a.click();
};
This works completely fine from images that are from open websites, like google.com or Wikipedia commons
However, for images from websites like Pixabay, Pexels, Freepik instead of downloading the Image it opens the image URL in the same tab and gives me 403 forbidden error in the console
I completely understand why this error happens, but what I don't understand is how to fix it? If I right-clicked on the image then hit save image as no error will appear and I will be able to download the image normally, how can I do this with javascript programmatically?
It works using the approach from accepted answer here: Chrome 65 blocks cross-origin <a download>. Client-side workaround to force download? , with a minor change. Instead of using mode "cors" use "no-cors". Apparently there is a cors error with some domains when downloading directly from url.
Updated: It does not work if the server does not allow cros-origin requests. Making the request with "no-cors" will succeed, but the response body will not be available. So this is NOT a solution.
You can use javascript fetch to download the random selected image from url address.
Code:
JS:
<script>
function downloadImage(url, name){
fetch(url)
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = name;
document.body.appendChild(a);
a.click();
//window.URL.revokeObjectURL(url);
})
.catch(() => alert('An error sorry'));}</script>
HTML:<button onclick="downloadimage('https://pixabay.com/get/g2cc1f3e1fe58926edc20db6cf67be6dd1614d93b06e934118288e4c57d5228c60c50de32506ac83ffdabc6fe20a6a01b3c7504b82965e6043e9038185180f3ae_1920.jpg', 'download.jpg')" >download</button>
example:
https://viena.lovestoblog.com/bakDownload/bak.php

Download a PDF link as a file in the same page instead of opening in browser

In my application written in Ionic 5 and Angular 8, I am in need to download multiple PDF links (file) in the same page on click of the link. I tried but the PDF links are opening in browser. Request to help me achieve this functionality.
https://stackblitz.com/edit/ionic-yzzwov?file=pages%2Fhome%2Fhome.html
The download attribute appears normal when same-origin, otherwise it will appear the same as without download attribute.
list three solutions:
Package the file into a file type that cannot be opened directly by the browser, such as ZIP
Through forwarding by the back end, the back end requests a third-party resource and returns it to the front end, which saves the file using tools such as file-Saver
If the third-party resource the URL points to has CORS configured, you can request the file through XHR
downloadFileXHR(filePath, fileName) {
var xhh = new XMLHttpRequest()
xhh.open('get', filePath)
xhh.responseType = 'blob'
xhh.onreadystatechange = function () {
if (xhh.readyState === 4 && xhh.status === 200) {
var blob = new Blob([xhh.response])
var csvUrl = URL.createObjectURL(blob)
var link = document.createElement('a')
link.href = csvUrl
link.download = fileName
link.click()
}
}
xhh.send()

how to set content-disposition = attachment via javascript?

How can I set content-disposition = attachment via javascript?
Basically, I would like to force a "SaveAs" operation after a page has loaded via Javascript, using Firefox.
How can I do this ?
Content-Disposition is a response header, ie. the server must return it. You can't achieve this with client-side javascript.
HTML only: use the download attribute.
<a download href="http://upload.wikimedia.org/wikipedia/commons/b/bb/Wikipedia_wordmark.svg">Download</a>
Javascript only: you can save any file with this code:
function saveAs(uri) {
var link = document.createElement('a');
if (typeof link.download === 'string') {
link.href = uri;
link.setAttribute('download', true);
//Firefox requires the link to be in the body
document.body.appendChild(link);
//simulate click
link.click();
//remove the link when done
document.body.removeChild(link);
} else {
window.open(uri);
}
}
var file = 'http://upload.wikimedia.org/wikipedia/commons/b/bb/Wikipedia_wordmark.svg';
saveAs(file);
1.Use Anchor "download"(HTML5) attribute
<a href='abc.pdf' download>Click Here</a>
2.Create href programmatically using js,
const link = document.createElement('a');
link.href = '/xyz/abc.pdf';
link.download = "file.pdf";
link.dispatchEvent(new MouseEvent('click'));
According to Mozilla doc Anchor element, download attribute(HTML5) instructs browsers to download a URL instead of navigating to it.
Important Notes:
This attribute only works for same-origin URLs.
Although HTTP(s) URLs need to be in the same-origin, blob: URLs and data: URLs are allowed so that content generated by JavaScript, such as pictures created in an image-editor Web app, can be downloaded.
So the above js method to create anchor element dynamically and using it download the file will only work for the same origin files i.e
There are two ways to handle this problem ->
Client-side
Server-side
Client-side solution:->
A work around for this problem, refrenced in second Note i.e a blob object can be used, with the help of fetch js API
url = 'https://aws.something/abc.pdf';
fetch(url, {
method: 'GET',
}).then(function(resp) {
return resp.blob();
}).then(function(blob) {
const newBlob = new Blob([blob], { type: "application/pdf", charset: "UTF-8" })
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
const data = window.URL.createObjectURL(newBlob);
const link = document.createElement('a');
link.dataType = "json";
link.href = data;
link.download = "file.pdf";
link.dispatchEvent(new MouseEvent('click'));
setTimeout(function () {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(data), 60
});
});
Server-side solution:->
The other option is if you can control the server side response headers then this may be the best option.
In a regular HTTP response, the Content-Disposition response header is a header indicating if the content is expected to be displayed inline in the browser, that is, as a Web page or as part of a Web page, or as an attachment, that is downloaded and saved locally.
e.g
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
For a file hosted on AWS , its response headers can be edited, these can be changed in meta data, add the content disposition header in the meta data in the file or the folder propertities, add key as content-disposition and value as attachment,
content-disposition : attachment
Now whenever this file is hit from a browser it would always download instead of opening, now if u use this file link in a anchor tag it would be downloaded directly with use of download html tag.

Categories