11

I have a site where users are prompted to download files from external resources. Since the external file names are hashed and the user downloads multiple files, it's very hard for users to know which file they download reaches what resource they requested. For instance, the file name of fdae442dafe42.zip could be production-resources.zip.

I'm looking for ways to have it so the browser will download the file as a different name. Below are some of my ideas and why they won't work, but you may be able to find a workaround.

Just a note, I don't have any control over the external resource. I won't be able to make changes to the headers or anything else. My service is a website that mostly targets Desktop Users. Android and iOS solutions won't be that beneficial.

Download Attribute

This method was working for a while in Google Chrome and Firefox, but then they started to follow the W3 HTML5 spec. The external resource requires to send the header of Content-Disposition in which Google Chrome and Firefox didn't check before.

PHP Proxy Download

I know that I could have a PHP script make a request to the external resource and then deliver it to the end user while changing the headers and name to fit my needs. The issue is the site has high traffic and each user downloads about 1-2GB of data. My servers are not able to handle this type of traffic and upgrading the server will probably be too costly.

Rename Files with External Application

I was considering using an external application (Possibly a Chrome / Firefox Extension) that will rename the files after they finish downloading. But considering a large enough of my audience are one time visitors, asking them to download an application or extension is very unlikely.

Flash or Java Embedded Solutions

I am considering using a Java or Flash embedded file that will handle the file downloads, but I don't know enough about either platform. From what I can tell, Flash doesn't have much control over the user's file system, so this could be an issue. Java will be able to do this task, but I was really hoping I wouldn't have to use Java since it's often insecure and requires a large download to install it (same issue as External Software idea).


If you have any ideas on what I could possibly do to solve this issue, they would be greatly appreciated. I'm not looking for any code, just ideas on how I will be able to accomplish the above task. I would like to thank you all for your time and expertise.

David
  • 4,313
  • 1
  • 21
  • 29
  • 8
    I'd vote to close this question as being primarily opinion based; answers to this question aren't going to solve the problem, they will just give you and whoever finds this question in the future even more things to think about. Unfortunately, it has an open bounty, and as such cannot be voted on for closing. – Mike 'Pomax' Kamermans Jul 21 '14 at 16:40
  • 3
    I'm not asking if Solution 1 is better than Solution 2. All the available solutions I currently have thought of will not work. I'm looking for a Solution to the issue I'm having, not an opinion on what solution I should use, since currently there are none. – David Jul 21 '14 at 16:43
  • Are the users downloading files “randomly” (by their own choice, _I want files `foo` and `bar`, I don’t care about the rest just now_), or do they have to download files/resources `A`, `B` and `C` to complete some kind of “package” that they can work with afterwards? (so basically work off a list of files and d/l them all) – CBroe Jul 21 '14 at 16:46
  • They are selecting what files to download, but usually a sequence of them. They are videos split up into segments. Some users only will want files 4,5,6 while others may want 1,2,3,4,5,6,... – David Jul 21 '14 at 16:47
  • I don’t see a totally “fool-proof” option here, at least not without proxy-ing the requests – but to make it easier for the user you could f.e. add a click handler to each download link, that copies the desired file name into their clipboard via JS, so that when the download dialog appears they simply would have to paste that into the field with the filename suggested by the remote server (that field should have focus already anyway in most browsers, so a simple `[ctrl]+[v], [enter]` could be all that’s needed. […] – CBroe Jul 21 '14 at 16:52
  • […] That would not work if the user was to open several download links at once (in background tabs maybe), of course – but that’s rather a matter of explaining it properly to the user beforehand, I think. – CBroe Jul 21 '14 at 16:56
  • Another idea, if you have a closed user base (or maybe even an intranet-kind of situation): Then you could maybe _require_ use of a certain download manager – and try and find one that accepts a kind of “download list”, with file names and target URLs already specified (a bit like a “playlist”, but for download). That list you could compile dynamically, f.e. by letting users chose files to download via checkboxes, and clicking a button “download via D/L manager XY now” that generates that list … and then they’d have to feed only that list to the D/L manager (or automated start of D/L manager.) – CBroe Jul 21 '14 at 16:57
  • This is what I'd have voted to close for. While stackoverflow seems a good place to illicit expert opinions, this is now a comments discussion instead of the kind of Q/A that stackoverflow is for. While sounding "unfair", these kind of discussions just aren't what the site was set up for, to the point that http://stackoverflow.com/help/dont-ask explicitly asks you to please not post these kind of questions. – Mike 'Pomax' Kamermans Jul 21 '14 at 17:31
  • 1
    I would say with what you doing using a Desktop Language E.G c# and build a download manager application would be better (no load on a server for downloads) if you want to keep information it can send it to your server, the only downside is that users would have to use your application to access the system for you to get the data. – Barkermn01 Jul 25 '14 at 12:20
  • you can use A[download], that's what it's for. FF and chrome did not start requiring the CD+attachment header, nor does the spec require it; from your link: "In cross-origin situations, the download attribute has to be combined with the Content-Disposition HTTP header, specifically with the attachment disposition type, to avoid the user being warned of possibly nefarious activity". Warning != preventing, and that's only for off-site downloads. Chrome wants window.URLs instead of dataURLs now, but that's a different issue and a minor one to fix. – dandavis Jul 25 '14 at 17:51
  • @dandavis, For Firefox 20+ the download attribute only works for same-origin requests. As for Chrome 35+, it's the same case. It will only work if it's the same origin. Using the download attribute will no longer work. https://code.google.com/p/chromium/issues/detail?id=373182#c24 – David Jul 26 '14 at 00:20
  • it doesn't say it won't work. it says "M-35 onwards will only honor the suggested filename if the final resource URL is same-origin as the document". so the file will still download, but the type will influence the file ext is my understanding... – dandavis Jul 26 '14 at 01:50
  • Could YOu please explain, why solution is not ok? – Jacek Kowalewski Jul 26 '14 at 08:35
  • If everyone who thinks a[download] will work, please check out this [JSFiddle](http://jsfiddle.net/4AX42/) which will only allow you to download / rename the last option. I tested this both in Chrome and FF. – David Jul 26 '14 at 12:54

3 Answers3

1

What is this external resource you are referring to?

If it happens to be Amazon's S3, it allows you to generate download URLs and specify the Content-Disposition that should be present in the response from their server upon download. There you can encode what the filename the browser should use when saving the file.

If it's another service, take a look at its documentation, maybe it has similar feature.

klandaika
  • 357
  • 3
  • 11
0

If you're authenticated on destination server via Access-Control-Allow-Origin then maybe combining those two methods would help you:

How to set custom http headers when changing iframe src?

$.ajax({
    type: "GET", 
    url: "https://app.icontact.com/icp/a/",
    contentType: "application/json",
    beforeSend: function(xhr, settings){
            xhr.setRequestHeader("some_custom_header", "foo");},
    success: function(data){
        $("#output_iframe_id").attr('src',"data:text/html;charset=utf-8," + escape(data))
    }
});

JavaScript/jQuery to download file via POST with JSON data

$.post('/create_binary_file.php', postData, function(retData) {
  $("body").append("<iframe src='" + retData.url+ "' style='display: none;' ></iframe>");
}); 
Community
  • 1
  • 1
Zentoaku
  • 766
  • 4
  • 12
0

Use the "download" attribute of tag "a".

<a href="http://external.server/path/to/file" download="name_you_want.ext">download</a>

This should work with the latest Chrome and Firefox but not work on IE.

Huang Kevin
  • 181
  • 4
  • 4
    This doesn't even work inside of Chrome or Firefox anymore. If you can provide a working example, then I will accept this. Here is my example of it not working in Chrome 36 - http://jsfiddle.net/4AX42/ – David Jul 28 '14 at 14:36
  • 1
    oops, I checked the document again, on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a, the download is available for blob:URLs or data:URLs only. So I wanted to load the url via XMLHttpRequest as binary data then convert to data URL by URL.createObjectURL, but I suffered the cross-domain problem. So, it looks like an impossible mission, I am sorry. – Huang Kevin Jul 28 '14 at 15:12