Kaspar H
Kaspar H

Reputation: 179

Download file from Flask application running in Docker container

I'm making a Flask application which runs in a Docker container. Everything works fine so far, but now I want to make a GET method, which should return a file to be downloaded by the user. For this, I've tried the Flask functions send_file and send_from_directory. They both work when I run my application as is, but as soon as I put it in a Docker container, things stop working.

If I use send_file, I get a file not found error, although I can call print(os.path.isfile) using the same file path, and it will show up.

If I used send_from_directory using the correct path and file name then I get instead a 404 error.

Again, this is only when running from a Docker container. Could it be a permission issue?

Example of method:

class DownloadLog(Resource):
    def get(self):
        print(os.path.isfile('logfile.log')  # Returns 'True'
        return send_from_directory('.', 'logfile.log')

Upvotes: 1

Views: 1999

Answers (2)

adisakshya
adisakshya

Reputation: 11

Nearly a year late to answer this though,

When you execute flask_application as is and use send_from_directory(directory/path, filename, as_attachment=True), it sends files from your HOST OS file system (Windows, Linux, macOS).

When you execute flask_application inside docker container and use send_from_directory(directory/path, filename, as_attachment=True), it sends files from your WORKDIR (/app). As flask couldn't find the file in the WORKDIR, it reports 404.

If you want this to work in docker, you can ADD or COPY the files that you want the user to download and then use their path in send_from_directory, or you can use volumes also.

Hope It Helps!

PS: Today I went through the same!

Upvotes: 0

fullonic
fullonic

Reputation: 11

I was running into the same issue and I fixed it by passing the full file path instead of the relative path when the app is running in a container.

For example, when I'm running only flask, I can use something like:

send_from_directory(
    current_app.config["DOWNLOAD_FOLDER"], filename.jpg, as_attachment=True
)

However, if running the app inside a container, I need to change it to:

send_from_directory(
    os.path.join(os.getcwd(), current_app.config["DOWNLOAD_FOLDER"]),
    filename.jpg,
    as_attachment=True,
)

Basically os.getcwd() is the app root folder defined inside the Dockerfile or the docker-compose.yml file.

Upvotes: 1

Related Questions