Flask 中使用 make_response 下载大文件

在Flask中,可以使用make_response函数来实现下载大文件的功能。具体怎么操作呢,以我具体示例来说,其实很简单。以下是一个简单的示例代码,演示如何在Flask应用中使用make_response来下载大文件:

1、问题背景

在使用 Flask 框架开发 web 应用程序时,如果需要提供大文件下载功能,可能会遇到内存溢出问题。以下代码展示了一个尝试下载大文件的示例:

python 复制代码
raw_bytes = ""
with open(file_path, 'rb') as r:
    for line in r:
        raw_bytes = raw_bytes + line
response = make_response(raw_bytes)
response.headers['Content-Type'] = "application/octet-stream"
response.headers['Content-Disposition'] = "inline; filename=" + file_name
return response

当文件较小时(小于 1GB),这段代码可以正常工作。但是,当文件较大时(大于 1GB),就会抛出 MemoryError 异常。这是因为将超过 2GB 的二进制数据存储在一个字符串中可能会导致内存不足。

2、解决方案

为了解决这个问题,可以使用流式传输的方式来下载大文件。流式传输允许将文件分块发送,这样就可以避免内存不足的问题。

2.1 使用 Flask 的 stream_with_context() 函数

Flask 提供了一个 stream_with_context() 函数,可以将一个生成器对象转换为一个 Response 对象。生成器对象可以逐块生成数据,这样就可以避免一次性将整个文件加载到内存中。

以下代码展示了一个使用 stream_with_context() 函数的示例:

python 复制代码
from flask import stream_with_context, Response

@app.route('/stream_data')
def stream_data():
    def generate():
        # create and return your data in small parts here
        for i in xrange(10000):
            yield str(i)

    return Response(stream_with_context(generate()))

在这个示例中,generate() 函数是一个生成器函数,它逐块生成数据。stream_with_context() 函数将这个生成器对象转换为一个 Response 对象,这样就可以将数据流式传输到客户端。

2.2 使用 Flask 的 send_from_directory() 函数

如果要下载的静态文件,可以使用 Flask 的 send_from_directory() 函数。这个函数可以将静态文件直接从文件系统中发送到客户端,这样就可以避免内存不足的问题。

以下代码展示了一个使用 send_from_directory() 函数的示例:

python 复制代码
from flask import send_from_directory

@app.route('/download_file')
def download_file():
    file_path = 'path/to/file.txt'
    return send_from_directory(os.path.dirname(file_path), os.path.basename(file_path))

在这个示例中,send_from_directory() 函数将文件 /path/to/file.txt 发送到客户端。

2.3 使用第三方库

也可以使用一些第三方库来实现大文件下载功能。例如,flask-large-file-downloader 库可以帮助你轻松下载大文件。

以下代码展示了一个使用 flask-large-file-downloader 库的示例:

python 复制代码
from flask_large_file_downloader import LargeFileDownloader

app = Flask(__name__)
app.secret_key = 'super secret key'

app.config['LARGE_FILE_DOWNLOADER_DIRECTORY'] = 'path/to/directory'
app.config['LARGE_FILE_DOWNLOADER_BUFFER_SIZE'] = 1024 * 1024

lf_downloader = LargeFileDownloader(app)

@app.route('/download_file')
def download_file():
    file_path = 'path/to/file.txt'
    return lf_downloader.send_file(file_path)

在这个示例中,lf_downloader.send_file() 函数将文件 /path/to/file.txt 发送到客户端。

通过设置适当的响应头信息,浏览器会提示用户下载文件。generate函数会以流式方式逐块读取大文件内容,避免一次性加载整个文件到内存中。

请确保替换代码中的path_to_your_large_file为你实际的大文件路径。这样,当访问/download_large_file路由时,Flask应用会开始下载指定的大文件。如果有更好得建议可以评论区留言讨论。

相关推荐
码事漫谈2 小时前
骂AI,会让它做得更好吗?
后端
“AI国潮设计-小江”2 小时前
《Python+SDXL实战:用ControlNet精准控制“英歌舞翻糖吐司”构图,附批量生成脚本》
开发语言·人工智能·python·prompt·aigc
程序喵大人3 小时前
【C++入门】编译链接模型 - 01 一个 C++ 程序是怎样变成可执行文件的
开发语言·c++·编译链接模型
wenwen_chao3 小时前
Python学习与开发资源合集:实用技巧与工具推荐
python
陈随易3 小时前
bm2,Node.js 与 Bun 项目部署新选择
前端·后端·程序员
for_ever_love__4 小时前
函数——参数、lambda、*args与作用域
python·函数·大模型开发·编程基础
东莞市云毅网络有限公司4 小时前
企业资料时效性判定:Last-Modified、正文日期与版本字段三路交叉
python·sqlite·自动化运维·geo·数据监测
Query*4 小时前
深入浅出LangGraph【一】_基础篇
python·ai·langchain
架构技术专栏4 小时前
AI Agent 框架怎么选:从一次制度查询拆出技术边界
后端·面试
sunshine22 girl4 小时前
Java学习七 Java 项目实战1-项目创建和主页面搭建
java·开发语言·学习