I have a download button on my page that looks like this:
<a download="test.jpg" href="data:application/octet-stream;base64,/9j/4AAQSkZ...">Download</a>
The href attribute is populated by JavaScript, and on my test server it functions exactly as I'd expect it to: it prompts a 'Save As' dialogue box with the filename "test.jpg".
However, when I use the exact same code on a different, live server, the filename is dropped.
In Chrome it saves as 'download', without a file extension
In Firefox it saves as a seemingly random string, again without a file extension
Any ideas what could be causing this difference in behaviour across the two servers?
This is a security measure applies when saving off-site downloads. since the prototcols don't match (data vs http), it's considered a different site, and a default names gets applies. Use URL.createObjectURL instead of base64 to feed the download's href. you can get a dataURL to Blob routine in my downlod.js library, then feed the Blob to createObjectURL().
Related
The only solution I've found it to grab the link with getElementsByClassName then inject it into an html snippet on the page, but it looks so fake, and is also unnecessary (I don't want all the links)
I want to right click the link (one at a time) and show it to the next tab. If I right click the link the server sends me a download prompt. How can I evade this?
I think the browser decides to download a file or display it based on its MIME type.
If the server is under your control, you should make sure you supply the correct Content-Type HTTP header (e.g. you have to call a library function in PHP, and there should be a similar way to do that in other languages).
Otherwise, for a purely client-side solution in JavaScript, you can fetch the file with an XMLHttpRequest (most JavaScript toolkits have wrappers around it). Then, you can convert it to base 64, prefix the result data:image/png;base64,, and use it as the src attribute of an img element (thanks https://stackoverflow.com/a/21508186/324969).
Note that for security aspects, grabbing arbitrary files and stuffing them in a data: URL might not be safe. I don't know if any cross-site scripting or CORS attacks could be built upon this. You'll have to ask a separate question to know if the client-side solution is unsafe. For the server-side, be careful not to set the wrong content-type for user-uploaded data, or for endpoints of your service (e.g. letting the client-side send you in the request the Content-Type that it would like, as tempting as it looks, is a big no-no).
To open the image in a new tab, you can use window.open as usual, but download the image beforehand (using XMLHttpRequest) and put the data:image/png;base64,… as the URL of the new tab.
Since you can already see the images by placing their URL in an img tag, you can paint that img on a , extract a PNG from the canvas, craft a data:image/png;base64,… URL from that, and then either automatically open many tabs with these URLS, or write in your page a series of links to data: URLs.
You could also have a link to a tiny web page with just the img tag that you currently use: link text.
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.
I'm trying to figure out how to call the File Save As Command in Firefox
(the one you get when you right click an image and save it) to save an image using JS (or if there is something else I can use, I would be grateful if you pointed me in that direction). I am looking for an example of how to open the Save As menu and pre-fill the file name field ... I've been searching furiously and have come up with zip. In my search I saw that you cannot directly save a file to disk, but is it impossible to call the save as function? Any suggestions would be greatly appreciated!
Edit:
I'm not looking to make this code available to everyone, and the java script is client side, I'm just writing a small script to make saving photos a little easier in terms of naming them.
-Will
No you can't do this, and really you are trying to find a solution in a way that does not embrace the internet and the way people interact with content. What you are trying to do is call on Operating System operation from Javascript. If there were anyway this would be possible, I don't think it is at all, it would be a very poor solution. Think about all the different Operating Systems Firefox is being used on. If you found a solution for Windows 7, what about an Apple Mac running Firefox?
What you should consider is that a User decides whether to Save something to their computer, not the programmer of the application. Provide a link to the file, most users know how to right click a link and select Save As. Add help tip explaining what to do as well.
To give a File a specific name or even start an automatic download when a User clicks or takes some kind of action, you can create a response from your server that is a PDF,Excel,Jpeg,Doc,Docx or many other files types. The server can load the file in memory and sent it as a response with the proper header information in the response.
For example to set a specific name for the file when the user downloads you can set your Response header with something like:
header('Content-Disposition: attachment; filename="downloaded.pdf"');
You can use the anchor element's download attribute to specify that a link is to be downloaded. Note that this is not implemented in all browsers, Chrome, Firefox, and Opera currently support it
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
HTMLAnchorElement.download
Is a DOMString indicating that the linked
resource is intended to be downloaded rather than displayed in the
browser. The value represent the proposed name of the file. If the
name is not a valid filename of the underlying OS, browser will adapt
it. The value is a URL with a scheme like http:, file:, data: or even
blob: (created with URL.createObjectURL).
Demo
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillRect(25,25,100,100);
ctx.clearRect(45,45,60,60);
ctx.strokeRect(50,50,50,50);
var link = document.getElementById("link");
//Set href to the data url that you want downloaded
link.href = "http://placehold.it/350x350";
//set download to the default filename you want to use
link.download = "image.png";
<canvas id="canvas" width="150" height="150"></canvas>
Click to download
You can also specify a regular url to a file, but note that if the server sends a filename header: Content-Disposition ... filename... that it will overwrite whatever you have in the download attribute.
I have created a shortcut file by going to Desktop -> new shortcut and entered link.
Now I have uploaded this shortcut file (*.url) on the
root on my server as shortcut.url
When i directly access mysite.com/shortcut.url, it does not start the download of it but instead show the content of the .url file.
Now on my page where i link to mysite.com/shortcut.url, I have tried the following methods:
How to start automatic download of a file in Internet Explorer?
But noone of them seems to work in Chrome (I though that if it their answers work in IE then Chrome it would too).
How is it possible to start downloading of this type of file, on click?
Generally speaking, a browser will fetch a resource in download mode (rather than displaying directly) if the content type is one that it cannot handle, and no plugins can handle. The easiest way for that to be the case is by using the content type for generic binary files:
Content-Type: application/octet-stream
Basically, configure your web server to use this content type (often called a MIME type) for .url files. How you do that depends on what server you're using.
I am accessing an existing WCF web service (which returns a PDF as a byte stream) using jquery's ajax methods.
When the call to the service completes, I end up with a javascript variable containing a PDF (the variable has the binary data in, starting "%PDF-1.4...").
I'd like to display this PDF in a new browser window, but I'm having difficulty achieving this.
My research so far shows that I might be able to achieve what I want using a data: uri, so my code that's called when the ajax call completes is as follows:
function GotPDF(data)
{
// Here, data contains "%PDF-1.4 ..." etc.
var datauri = 'data:application/pdf;base64,' + Base64.encode(data);
var win = window.open("", "Your PDF", "width=1024,height=768,resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no");
win.document.location.href = datauri;
}
This causes a new browser window to open, but the contents are blank.
Interestingly, if I point my browser (IE9) at an existing file on my local disk by using a file: uri, such as file://c:/tmp/example.pdf, then I get the same result, i.e. a blank window.
Is there any way I can display this PDF data?
Code you wrote does not display anything, simply open a blank window (location.href is an hash for browsing history, not the content of the page).
To display a PDF you have, at least, following options:
× Embed the PDF viewer inside an object tag. It may not be as straightforward as you may imagine, take a look to this post for sample code. In short it should be something like this:
<object data="your_url_to_pdf" type="application/pdf">
<div>No PDF viewer available</div>
</object>
That's basic code but I suggest to follow what I say in the linked post if you need higher cross-browser compatibility (it also contains a few examples about how you might try to detect support for a PDF viewer).
× Download the file to local computer (simply add the full URL of your web service method that produces the file, do not forget to add the proper Content-Disposition in the header).
× Open the file into a new browser window. Create a normal a tag as you point to a PDF file on-line that you want to display in a new window. Change the href to javascript:functionName and in that function produce the URI you'll use to call the web service method.
Whatever you'll do, do not forget to set the proper MIME type in your response moreover you method shouldn't return a byte stream (even if encoded) but a valid response for your web browser.
If you are using <embed> or <object> tag to display a streamed PDF file (or other file types) from a server as in:
<object data="SomeServlet?do=get_doc&id=6" type="application/pdf" width="800" height="400">
make sure the server sends the proper http content-disposition value, which in this case would be inline.