Flask / Python:从绝对路径创建zip文件失败-没有此类文件或目录

时间:2019-02-08 08:46:56

标签: python flask server zipfile

我正在创建CKAN插件,以允许用户从数据库服务器选择和下载多个资源(文件)。 我用一些Python代码创建了flask视图函数,该函数应使用请求的资源创建一个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命令失败,并显示“无此类文件或目录”错误。

有什么问题的主意吗?

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

结果证明,我最初的猜测是正确的,除了通过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}完成的,但这可能取决于您的框架/应用程序。