Force file download instead of opening in browser Using HTTP Header and Flask
-
Brief introduction of HTTP Header:
HTTP header fields are used between browser and web server for communication. It specify configurations and cookies that lay a foundation for the modern Internet.
An example of Request Header field: "user-agent"
(what Operation System and Browser Version the client is using).
user-agent: Mozilla/5.0 (Linux; Android 6.0.1; SM-G532G Build/MMB29T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.83 Mobile Safari/537.36 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7
An example of Response Header field: "cache-control"
(The cache policy).
cache-control: private, max-age=0 cache-control: public, max-age=30672000
The story of Content-Disposition:
There are 2 main methods for modern browser such as Chrome and Firefox to handle HTTP Response, show the content inline in the browser (open in browser), or download it as an attachment and saved at your laptop's local disk. In order to tell how browser showed deal with the data, web server needs to add "Content-Disposition" field in the HTTP response header.
if "Content-Disposition"
field is not specified, "inline"
will be used as default (open in browser), which is equal to:
Content-Disposition: inline
To force file download, specify "Content-Disposition"
HTTP Header field as below:
Content-Disposition: attachment
To rewrite the attachment's name, specify filename
within "Content-Disposition". if filename
is not specified, the original file name will be used.
Content-Disposition: attachment; filename="test.txt"
Add Content-Disposition HTTP Header in Flask
If you are using Flask as your website project's framework, It's easy to set up any HTTP Header field. You can set a rang of URL with '/download/'
prefix. Then add Content-Disposition
HTTP header to all HTTP Responses!
@app.after_request def after_request(response): if str(request.path).startswith('/download/'): response.headers['Content-Disposition'] = 'attachment' return response
HTML5 Attribute Alternative
There is a new attribute in HTML5 specification, by adding download
tag to any link to achieve force download.
<a href="/download/force_file_download_test.txt" download>source code</a>