File.Download
Commands for downloading files.
SECURITY NOTE: Browsers require that all downloads are initiated by a user event. So rather than allowing malicious sites to put files on your computer however they please, the user at least have to click a button first. As a result, the following commands only work when they are triggered by some user event.
Download a String
as a file. Maybe you markdown editor in the browser,
and you want to provide a button to download markdown files:
import File.Download as Download
save : String -> Cmd msg
save markdown =
Download.string "draft.md" "text/markdown" markdown
So the arguments are file name, MIME type, and then the file content. In this case is is markdown, but it could be any string information.
Download some Bytes
as a file. Maybe you are creating custom images,
and you want a button to download them as PNG files. After using
gren/bytes
to generate the file content, you can download it like
this:
import Bytes exposing (Bytes)
import File.Download as Download
savePng : Bytes -> Cmd msg
savePng bytes =
Download.bytes "frog.png" "image/png" bytes
So the arguments are file name, MIME type, and then the file content. With the
ability to build any byte sequence you want with gren/bytes
, you can
create .zip
files, .jpg
files, or whatever else you might need!
Download a file from a URL on the same origin. So if you have a website
at https://example.com
, you could download a math GIF like this:
import File.Download as Download
downloadMathGif : Cmd msg
downloadMathGif =
Download.url "https://example.com/math.gif"
The downloaded file will use whatever name the server suggests. So if you want
a different name, have your server add a Content-Disposition
header like
Content-Disposition: attachment; filename="triangle.gif"
when it serves the
file.
Warning: The implementation uses <a href="..." download></a>
which has
two important consequences:
- Cross-origin downloads are weird. If you want a file from a different
domain (like
https://files.example.com
orhttps://www.wikipedia.org
) this function adds atarget="_blank"
, opening the file in a new tab. Otherwise the link would just take over the current page, replacing your website with a GIF or whatever. To make cross-origin downloads work differently, you can (1) make the request same-origin by sending it to your server and then having your server fetch the file or (2) fetch the file withgren/http
and then go throughFile.Download.bytes
. - Same-origin downloads are weird in IE10 and IE11. These browsers do not
support the
download
attribute, so you should always get thetarget="_blank"
behavior where the URL opens in a new tab. Again, you can fetch the file withgren/http
and then useFile.Download.bytes
to get around this.
Things are quite tricky here between the intentional security constraints and
particularities of browser implementations, so remember that you can always
send the URL out a port
and do something even more custom in JavaScript!