Hacker News new | past | comments | ask | show | jobs | submit login

The <a download> attribute sounds great on paper, but if request fails for whatever reason your user will, very confusingly, download a file named exactly as you specify but with error page HTML as contents.

There is no straightforward way[0] for you to gracefully handle an error, which is quite an oversight once you factor in that network isn’t always reliable.

Having used it at first, I switched to server-side logic where I return data with Content-Disposition header if everything went well or redirect the user to show a proper error message in case of a problem.

[0] I imagine this could be worked around with some JS-based preflight or other trickery—which sounds like a suitable solution only if you have no control over the headers returned for some reason.




> The <a download> attribute sounds great on paper, but if request fails for whatever reason your user will, very confusingly, download a file named exactly as you specify but with error page HTML as contents.

Though that is at least consistent with other download options like right-click/save-link-as, so is probably not incorrect behaviour.


Yes, it’s probably the same behavior: https://html.spec.whatwg.org/multipage/links.html#downloadin.... Step 7 is mostly where any improvements would go, I imagine.

I’m OK with “Save as” (“Download linked file”, etc.) behaving as it does: it is more or less intuitively clear that with it we sort of “cheat” and use browser’s semi-hidden feature to interact with a website in ways not necessarily intended by its engineers. With the download attribute, however, any confusing outcome falls squarely on me, the developer, so I’d rather stick with plain links and response headers as a mechanism I have more control over.

There may be some workarounds to make download behave adequately in case of an error, such as having your server behave in some way that causes browser’s fetch sequence to fail with a low-level error. Unless I’m missing something, it seems like proper network error is the only condition under which download can actually fail, and I don’t think a typical web framework setup is equipped to intentionally cause that to happen. I doubt it’s worth the bother—if you have control over the server then why not drop the attribute and just return the appropriate headers.


I've had to do something like that for an awful application where the frontend did chunked downloads, but didn't check properly for the status code, embedding error pages directly in the downloaded file.

As I had no control over the frontend itself, I configured the reverse proxy so that for requests to download endpoints, all error responses would instantly close the connection to the client.

Your post makes me think that I could generalize this so that any error to an explicit download would close the connection at the network level. It would be quite tricky to be able to distinguish between implicit and explicit downloads, but I think that if the frontend, backend and reverse proxy coordinate well together, it can be done without introducing other problems.

Of course, it's a big hack that's not worth the bother.


This is true of pretty much anything that wants to directly invoke the browser's download mechanism. AFAICT the options are either:

1. Use JS, in which case one can handle errors and otherwise be involved in the request / response process. However, if you wish to offer a "download" funciton, this necessitates downloading all the data into JS memory before offering it to the user.

2. Use form-posting with `Content-Disposition`. One can no longer be involved with the request and response. And any response which does not have `Content-Disposition` will result in the browser redirecting. However, the user will be able to directly stream the download without your page being involved beyond initiating the request.

Since the data downloads are gigabytes in our case, we opted for (2). But I would also love to hear if I'm wrong about this trade-off.


Huh. Whenever I've used it, things have all been on the same domain so this doesn't come up - good to know.


If your user clicks the link with download attribute and your server (or reverse proxy, or CDN, etc.) issues an error page, user agent downloads the HTML of that page and saves it under the filename you provided. Domain does not enter the picture.

(Correction: per spec, the domain does enter the picture in that cross-domain <a download> is not supposed to work at all without Content-Disposition response header; that’s slightly different matter to what’s discussed.)


In my uses, I can be almost certain that I won't get a 404 back as a response, unless I forgot to do something - although the others are a concern. Even though Netlify allows setting headers and redirects, I obviously don't control the image they use or the CDN generally.

Something to watch out for.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: