I have an HTML string in javascript variable. I have to save/Download the string as a file on link click. It should be cross browser compatible.
I thought window.open with attachment Content-Disposition header, but not good solution because popup may be blocked.
As mentioned here, you could use downloadify: https://github.com/dcneiner/Downloadify. The client will need flash though.
Related
Say I have:
a webpage with an iframe: <iframe src="" style="display:none;"></iframe>
an URL pointing to a PDF document: http://www.example.com
some javascript that will do iframe.src = pdfurl
a button that will trigger such javascript
if the browser is going to display the PDF inline, the button will
say "view pdf" and when clicked will make the iframe visible
otherwise it will say "download pdf"
I found a way to detect whether the pdf has been loaded in the iframe: reading iframe.contentDocument.contentType after onload has fired, but
this won't allow me to display the correct button
onload does not fire if the file is being downloaded
Thanks :)
To tell the client's browser to download a response as a file, set the Content-Disposition HTTP header to 'attachment' in your response. This is no guarantee, but it's the proper method of telling the browser how to handle the content.
In modern Browsers, JavaScripts global Navigator object has a plugins property, filled with an array of Plugins, if you can find a Plugin for Mimetype application/pdf, you can safely assume that the browser will display pdf files inline, as long as the server does not explicit send content-disposition: attachment headers, of course.
ยง 8.9.1.6 PDF viewing support
window.navigator.pdfViewerEnabled
Returns true if the user agent supports inline viewing of PDF files when
navigating to them, or false otherwise. In the latter case, PDF files
will be handled by external software.
MDN web docs article.
Browser compatibility table
You could send a HEAD request to that resource and check what Content-Type and Content-Disposition values are being sent back. Based on these information you could determine whether a browser would display or download that resource.
I have a PDF file as a blob object. I want to serve to my users, and right now I'm doing:
html = '<iframe src="' + URL.createURL(blob) + '">';
That works fine for people that want to use their in-browser PDF tool.
But...some people have their browser set to automatically download PDFs. For those people, the name of the downloaded file is some random string based on the blob URL. That's a bad experience for them.
I know I can also do:
<a href="blobURL" download="some-filename.pdf">
But that's a bad experience for the people who want to use in-browser PDF readers, since it forces them to download the file.
Is there a way to make everybody have good file names and to allow everybody to read the PDF the way they want to (in their browser or in their OS's reader)?
Thanks
At least looking at Google Chrome, if the user disables the PDF Viewer (using the option "Download PDF files instead of automatically opening them in Chrome") then window.navigator.plugins will show neither "Chromium PDF Plugin" nor "Chromium PDF Viewer". If the option is left at the default setting, the viewer will show in the plugin list.
Using this method, one can utilize window.navigator.plugins to check if any of the elements' names are either of the aforementioned plugins. Then, depending upon that result, either display a <iframe> or a <a href="blobUrl" download="file.pdf">. For other browsers I imagine that different methods would have to be used. You can also check for a "Acrobat Reader" plugin, which some machines may have instead, or even just the word "PDF".
On a side note, it does look like it is possible to detect if the default Firefox PDF viewer is enabled by using http://www.pinlady.net/PluginDetect/PDFjs/ .
Try to append &filename=thename.pdf to the binary, metadata or http header:
Content-Disposition: attachment; filename="thename.pdf"
I have looked through the documentation of createObjectURL(blob), it will always return a unique and specific format of url. It is not possible to change the URL here.
The plugin thing is not consistent across browsers.
Now here is my radical idea
Find or create(if not available) a js library that can create and save PDF files to server from blob. (I looked through some of them like 'jsPDF','pdfkit' but none of them use blob)
Save the file to server with a valid name
use the above name in the iframe.
Is it possible to force a download through JS or Javascript i-e the web page should not open the file in new tab in the browser but to pop up to let the user to choose eith "save as" or open with ???
With the advent of HTML5 you could just use the new property download in the anchor tag.
The code will look something like
<a download="name_of_downloaded_file" href="path/to/the/download/file"> Clicking on this link will force download the file</a>
It works on firefox and chrome latest version. Should I mention that I didn't check it in IE? :P
Edited the download attribute after comment from sstur
https://caniuse.com/#feat=download
dynamic create link and click it with download attribute for force download as file:
var anchor = document.createElement('a');
anchor.href = this.props.download_url;
anchor.target = '_blank';
anchor.download = this.props.file_name;
anchor.click();
Take a notice that i didn't even added it to DOM, so it's fast.
P.S download attribute won't work with IE. But it will just open link in new tab.
http://caniuse.com/#feat=download
You can not force that behavior from JavaScript, the HTTP Headers need to be set on the server side:
Content-disposition=attachment; filename=some.file.name
The way you can solve the problem is to let your AJAX method redirect the user to the URL of the PDF:
location.replace('path/to.pdf');
(The above HTTP headers must be set for the PDF)
Update
At the time of this answer, it wasn't possible. Now it is, scroll down to see the other answer saying so.
No this is not possible with JQuery/JavaScript only.
You will need a server side script which returns you the file with a Content-Type (HTTP Header) which will force the browser to download your requested file. An possible value for Content-Type would be application/force-download.
No, it is not possible and thanks God it isn't. Otherwise I leave you to the imagination of what kind of files could be stored on your computer when you visit a web site without you knowing it.
As #Paul D. White pointed out in the comments section if you want to open the file inline (inside the browser) with the default program associated with it you could have the server send the Content-Disposition HTTP header. For example:
Content-Disposition: inline; filename=foo.pdf
I'm trying to make a downloader on my website which starts downloading the selected files but the problem is it is a music file which just opens up in a new window and starts playing it.
The script is (don't worry about the id part it is for the next part):
function downloadsong(id){
var url = ("/music/downloadablesongs/linkin-park/Minutes-to-Midnight/wake.mp3");
window.open(url,'Download')
}
If you can configure the server that hosts the files, you should be able to manipulate the HTTP headers to include a "Content-Disposition" header. This will prompt the user agent (browser) to save the file, rather than allow it to automatically detect/interpret the content.
The basic format is:
Content-Disposition: attachment; filename=$file_name.ext
It depends on the user's browser. Usually, plugins or built-in browser capabilities take over and play it instead of letting the browser download.
What you can do is to have the file carry no extension (ie. remove .mp3). That way, it won't be picked-up by plugins. The down side is additional work for the user, by having to add the extension manually.
Other way is simply use the download attribute. I think is the simplest way.
<a href="/music/downloadablesongs/linkin-park/Minutes-to-Midnight/wake.mp3" download>
See more here.
Is it possible to force a download through JS or Javascript i-e the web page should not open the file in new tab in the browser but to pop up to let the user to choose eith "save as" or open with ???
With the advent of HTML5 you could just use the new property download in the anchor tag.
The code will look something like
<a download="name_of_downloaded_file" href="path/to/the/download/file"> Clicking on this link will force download the file</a>
It works on firefox and chrome latest version. Should I mention that I didn't check it in IE? :P
Edited the download attribute after comment from sstur
https://caniuse.com/#feat=download
dynamic create link and click it with download attribute for force download as file:
var anchor = document.createElement('a');
anchor.href = this.props.download_url;
anchor.target = '_blank';
anchor.download = this.props.file_name;
anchor.click();
Take a notice that i didn't even added it to DOM, so it's fast.
P.S download attribute won't work with IE. But it will just open link in new tab.
http://caniuse.com/#feat=download
You can not force that behavior from JavaScript, the HTTP Headers need to be set on the server side:
Content-disposition=attachment; filename=some.file.name
The way you can solve the problem is to let your AJAX method redirect the user to the URL of the PDF:
location.replace('path/to.pdf');
(The above HTTP headers must be set for the PDF)
Update
At the time of this answer, it wasn't possible. Now it is, scroll down to see the other answer saying so.
No this is not possible with JQuery/JavaScript only.
You will need a server side script which returns you the file with a Content-Type (HTTP Header) which will force the browser to download your requested file. An possible value for Content-Type would be application/force-download.
No, it is not possible and thanks God it isn't. Otherwise I leave you to the imagination of what kind of files could be stored on your computer when you visit a web site without you knowing it.
As #Paul D. White pointed out in the comments section if you want to open the file inline (inside the browser) with the default program associated with it you could have the server send the Content-Disposition HTTP header. For example:
Content-Disposition: inline; filename=foo.pdf