简体   繁体   English

从 Docker 容器中运行的 Flask 应用程序下载文件

[英]Download file from Flask application running in Docker container

I'm making a Flask application which runs in a Docker container.我正在制作一个在 Docker 容器中运行的 Flask 应用程序。 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.到目前为止一切正常,但现在我想创建一个 GET 方法,它应该返回一个文件供用户下载。 For this, I've tried the Flask functions send_file and send_from_directory .为此,我尝试了 Flask 函数send_filesend_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.当我按原样运行我的应用程序时,它们都可以工作,但是一旦我将它放入 Docker 容器中,事情就会停止工作。

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.如果我使用send_file ,我会收到一个file not found的错误,尽管我可以使用相同的文件路径调用print(os.path.isfile) ,它会显示出来。

If I used send_from_directory using the correct path and file name then I get instead a 404 error.如果我使用正确的路径和文件名使用send_from_directory ,那么我会收到 404 错误。

Again, this is only when running from a Docker container.同样,这仅适用于从 Docker 容器运行时。 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')

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.基本上os.getcwd()是在 Dockerfile 或 docker-compose.yml 文件中定义的应用程序根文件夹。

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).当您按原样执行 flask_application 并使用send_from_directory(directory/path, filename, as_attachment=True)时,它会从您的HOST OS文件系统(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) .当您在 docker 容器内执行 flask_application 并使用send_from_directory(directory/path, filename, as_attachment=True)时,它会从您的WORKDIR (/app)发送文件。 As flask couldn't find the file in the WORKDIR, it reports 404.由于 flask 在 WORKDIR 中找不到该文件,它报告 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.如果您希望它在 docker 中工作,您可以ADD or COPY您希望用户下载的文件,然后在send_from_directory中使用它们的路径,或者您也可以使用卷。

Hope It Helps!希望能帮助到你!

PS: Today I went through the same! PS:今天我经历了同样的事情!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM