node/express Force browser to download file with custom name - javascript

I've built a node/express website for my university project that, after searching for an ID of a law, it shows a big table with all files in different formats and languages related with this id.
I use the module "http-proxy" to request and serve these files to client.
Nothing wrong when serving xml, xhtml, html and pdf files (every browser is able to directly view them).
I have problems with .zip and .rdf files. Files are not corrupted but they are losing the original name
when i click on ZIP icon, it gives me the download prompt, but I'm losing the original file name (the file will be called "proxy" or "proxy.zip", different behaviors on different browsers)
when i click on RDF icon, some browsers opens the file directly in browser, some browsers won't recognize the format, some browsers wants to download it with name "proxy")
So I discovered the HTML5 attribute "download" of the tag "a". It just solve my problem, anyway it is not supported on every version of Internet Explorer and Safari. Surfing the web I found some workarounds to add "Right click and save as..." after a div link when the page is viewed in IE or Safari, but this solution is not for me, because i'm not talking about a single link but a table full of links. And my site need to work also on mobile phones.
Is there any way to write some server-side code to force browsers to download files with a custom file name?
Here is the small piece of code of the proxy:
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({ ignorePath: true });
app.get('/proxy', function(req , res) {
var file = req.query.file;
var realurl = 'http://'+cfg.edb_opt.host+':'+cfg.edb_opt.port+cfg.edb_opt.rest+file;
console.log('Proxy: serving '+realurl);
proxy.web(req, res, { 'target': realurl });
});
All cfg* variables comes from a json configuration file to set the host, port, and starting path where files are contained.
Thanks in advance :)

You need to add a new header to the response object to indicate the file name and do a regular download.
res.set("Content-Disposition", "attachment;filename=somefile.ext");
You could also use "inline" if instead you want the browser to try to open the file within it self, like with Chrome does with pdf files.
res.set("Content-Disposition", "inline;filename=somefile.ext");
As per #Thomas suggestion, also is a good idea to include always the right content type:
res.set("Content-Type", "application/octet-stream");

In Express 4 and later, there are 2 helper functions to change the content-type and specify attachment disposition:
res.type("application/octet-stream");
res.attachment("filename.ext");
See docs for type and attachment.

Related

Read local text file using js/html file on on local machine

I've built a simple html page with javascript in a separate file, called on a button press.
I've opened the html file in chrome, and the path resembles: file:///home/tom/projects/index.html
The javascript needs to read a JSON file (file:///home/tom/projects/mydata.json) which is in the same directory, using a hardcoded path.
I'm really struggling to do this. As I understand, this is because I'm using client side js (meaning I can't use the fs library for example), which is limiting my options.
According to the question here, I can't load the file if I use the URL in the format: file:///home/to.... as it gives me the error:
Cross origin requests are only supported for protocol schemes: HTTP, data, chrome, chrome-extension, https.
If I start an HTTP-server, as the answer suggests, I can use server-side modules, but if possible I would like to avoid this.
I've noticed many answers that suggest using a dialog box like this:
var selectedFile = document.getElementById('input').files[0];
function readFile (file_path) {
var reader = new FileReader();
reader.readAsText(file_path);
console.log(reader.substring(0, 100));
};
but I can't make this work with a path in the form: file:///home/tom/projects/mydata.json
Is there a way to load a .json file from a file:///home/to.... format URL using client-side javascript, with a hardcoded path (ie not asking the user to select the file from a selection box)?
This is a deliberate security restriction, to stop a user from being given, and then opening, a HTML page which then tries to read their disk.
Run your page in a webserver (as that question suggested) then you can either load the JSON from a URL (e.g. something like http://localhost/projects/mydata.json) using JavaScript, or use a server-side language to fetch it and display it inside the rendered HTML. Either way will work, the first way is probably simpler and closest to what you've got now.
It's always far better to serve HTML pages from a HTTP server, the way it's intended to be.

How to serve blob and have good filename for all users?

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 Possibly to Access Firefox Save As Command Using JS?

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.

Starting download of an url shortcut file?

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.

Downloading a music file instead of playing it in the browser

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.

Categories

Resources