在使用shutil、flask和javascript创建存档时下载存档

问题描述 投票:0回答:1

我正在构建这个程序,我在烧瓶网络应用程序上索引我的外部硬盘驱动器,可以在其中下载文件。在通过

flask.send_file()
下载文件夹之前,需要先将其存档,因为 Flask 无法仅发送目录文件。

所以我通过

shutil.make_archive()
创建存档,完成后开始下载。

这里的问题是,某些文件可能会变得非常大,即使 Shutil 可以处理它们,也可能需要一些时间才能完成归档,因为这是在旧的外部硬盘驱动器上。

幸运的是,当 Shutil 开始创建存档时,它是可见的,因此可能会有一些用处。

这里是处理 zip 文件下载和创建的 javascript。这按预期工作:

async function download_file() {
    var download_path;
    if (!(path.includes('.'))) {
        const promise = await fetch(`/archive?path=${path}&name=${select}`, {method: 'GET'});
        download_path = await promise.json();
    } else {
        download_path = path;
    }
    var downloader_a = document.createElement('a');
    downloader_a.href = `/download?path=${download_path}`;
    downloader_a.click();
}

蟒蛇陪伴:

@app.route('/download')
def download():
    path = request.args.get('path')
    return send_file(drive + path, as_attachment=True)


@app.route('/archive')
def archive_folder():
    path = drive + request.args.get('path')
    name = request.args.get('name')
    shutil.make_archive('{}{}/{}'.format(drive, archiving_folder, name), 'zip', path)
    return jsonify('{}/{}.zip'.format(archiving_folder, name))

所以我相信这个问题是由于我的 javascript 函数的异步特性而产生的。我尝试的是从创建存档的 JavaScript 中删除

await
,以便它从此开始:

const promise = await fetch(`/archive?path=${path}&name=${select}`, {method: 'GET'});
download_path = await promise.json();

对此:

const promise = fetch(`/archive?path=${path}&name=${select}`, {method: 'GET'});
download_path = promise.json();

我认为这可能不太可能,因为当我这样做时,会下载不完整的存档,但我想在存档生成时下载它。有什么想法吗?

提前致谢。

javascript flask fetch-api shutil
1个回答
0
投票

通过使用评论中推荐的资源dave,我能够精确地实现我正在寻找的内容。

安装 zipstream-ng 并完成示例后,我将 javascript 下载功能更改为:

async function download_file() {
var downloader_a;
downloader_a = document.createElement('a');
if (!(path.includes('.'))) {
    downloader_a.href = `/zip_stream?path=${path}&name=${selected_item}`
} else {
    downloader_a.href = `/download?path=${path}`;
}
downloader_a.click();

对应的python:

from zipstream import ZipStream, ZIP_DEFLATED
@app.route('/zip_stream')
def stream_zip_file():
    path = drive + request.args.get('path')
    name = request.args.get('name')
    zs = ZipStream.from_path(path)
    return Response(
        zs,
        mimetype='application/zip',
        headers={
            "Content-Disposition": f"attachment; filename={name}.zip",
            "Content-Length": len(zs),
            "Last-Modified": zs.last_modified,
        }
    )

现在,当下载文件夹时,将传输该文件夹的 zip 文件。

© www.soinside.com 2019 - 2024. All rights reserved.