0

I have a flask app in which it has a button to download an HTML report. The download button when hit creates an xlsx file. It worked fine until that app was running on my local server because the python code found my Downloads directory no matter what os it is using python's os module.

Now the app is deployed on a remote server, in this case, how do you let the system know the client's download directory path where this xlsx file can then be created? Or any other pointers for a better solution if I'm missing something?

1
  • The server can't specify the download directory on the client, only the filename (eg. With Flask's send_file function, you can pass the attachment_filename arg which in turn passes the correct Content-Disposition HTTP header). See another answer I wrote which kinda relates to this topic.
    – v25
    Commented Jun 8, 2021 at 22:29

2 Answers 2

2

If i understand correctly - you want to specify a directory to which the file should be downloaded on users computer when he/she hits download button.

This is not possible, and is handled fully by the browser.

Browser processes the request/stream of special type and then creates the output file in the location specified by the user in browser settings. The os library which you mentioned relates to your server machine not client, so any os opertaions that you provide in your code will be executed on your server (like creating a file). So that's why it worked on your local machine - which was server and client at once.

Why is it disallowed?

Imagine a "virus file" being uploaded to your C:\Windows\System32. Web applications could be granted control over your machine with a simple button download. The huge security issue doesnt allow for client's machine access from web application

1
  • I knew why it worked when the app was on my local server, but I had no idea as to how to achieve the downloading part. The other answer that I accepted showed me the way to do it. I was completely on the wrong track. But thank you for the useful information, especially for highlighting the security threat that the way I was trying to do it would cause. Commented Jun 10, 2021 at 20:08
1

To serve a user a file to download, the webserver needs to deliver it in a special way. You can't use the os module to write to the user's computer. It worked locally, because your server was the same computer as your user environment in the browser.

The correct way to serve a user a file for downloading is to use flask's send_file method.

To show you the process, I've created an example below. In this example, I'm assuming that you have a function called build_report(...) which accepts a report_id and returns an io.BytesIO object containing the content of the xlsx file.

from flask import send_file

@app.route("/download-report/<report_id>")
def download_report(report_id):
    file_obj = build_report(report_id)
    return send_file(
        file_obj,
        mimetype="application/vnd.ms-excel",
        attachment_filename=f"report-{report_id}.xlsx",
    )

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.