【问题标题】:Flask/Python: creating zip file from absolute path fails - no such file or directoryFlask/Python:从绝对路径创建 zip 文件失败 - 没有这样的文件或目录
【发布时间】:2019-07-02 11:27:34
【问题描述】:

我正在创建一个 CKAN 插件,以允许用户从数据库服务器中选择和下载多个资源(文件)。 我使用一些 Python 代码创建了一个烧瓶视图函数,该函数应该使用请求的资源创建一个 zip 文件,但是即使我给出了绝对路径,创建也会失败并出现“没有这样的文件或目录”错误。

代码基于thisthisthis帖子,为了解决当前问题,我已经检查了herehere,但没有太大成功。

代码如下:

import zipfile
import io

def download_multiple_resources():
    if request.method == "POST":

        memory_file = io.BytesIO()
        with zipfile.ZipFile(memory_file, "w", zipfile.ZIP_STORED) as zf:
            for res in request.form.values():
                zf.write(str(res), 'download.zip')

return send_file(memory_file, mimetype='application/zip', as_attachment=True, attachment_filename='download.zip')

资源由用户通过表单选择,该表单发布请求。 表单提交请求文件的完整路径,因此如果用户选择下载testfile.txt,则在上面的代码中res 的值类似于http://localhost:5000/dataset/6192bb3b-6c4a/resource/dbe39d59-b938/download/testfile.txt。 (目前在我机器上的 docker 容器中创建的服务器上进行测试)

请注意,在我的浏览器中复制粘贴上述路径可以让我毫无问题地访问该文件。 但是,zf.write 命令失败并出现“没有这样的文件或目录”错误。

知道出了什么问题吗?

【问题讨论】:

  • 对于任何对此投反对票的人,您实际上可能会有所帮助并写下 1)您投反对票的原因,以便在必要时改进我的问题; 2)也许你对解决方案的想法?

标签: python flask server zipfile


【解决方案1】:

事实证明我最初的猜测是正确的,除了使用 http 请求读取文件之外,只需要使用 writestr() 而不是 write()。 这是完整的工作代码:

import zipfile
import io
import requests
from flask import request, send_file

def download_multiple_resources():
    if request.method == "POST":
        memory_file = io.Bytes.IO()
        with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_STORED) as zf:
            for res in request.form:
                f = requests.get(res, allow_redirects=True)
                zf.writestr('your_chosen_filename', f.content)
        memory_file.seek(0)

    return send_file(memory_file, mimetype='application/zip', as_attachment=True, attachment_filename="download.zip")

额外说明:如果您像我一样在外部服务器上工作,并使用此功能让登录用户下载文件,请确保将用户的凭据传递给 request.get() 调用以授权下载。在我的情况下,这是使用选项 headers={'Authorization': user.apiKey} 完成的,但这可能取决于您的框架/应用程序。

【讨论】:

    【解决方案2】:

    您说您想通过其绝对路径访问资源,但您的 res 示例值是一个 URL。

    我不认为zipfile.ZipFile.write 支持这一点,因为将文件添加到 zip 存档会使用文件系统中的元数据(时间戳等)。您将需要通过其本地路径访问资源,或者如果无法从应用程序容器访问,请先将其下载到临时位置。 (当然,后一种情况会剥离元数据。)

    【讨论】:

    • 感谢您的回答!我看不出绝对路径和完整 URL 之间的区别——它是服务器上的绝对路径——但我的技术水平不足以对此有更好的看法。我会按照您的建议尝试使用本地路径,如果可行,则标记为答案。下载我在服务器上的文件以压缩它并将其作为下载返回给用户似乎是一种非常低效的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2020-08-04
    • 2013-07-13
    • 1970-01-01
    • 2022-11-17
    • 2013-01-13
    • 2021-05-13
    相关资源
    最近更新 更多