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应用会开始下载指定的大文件。如果有更好得建议可以评论区留言讨论。

相关推荐
春涧草茶5 分钟前
慢就是快16-1协程
开发语言·前端·python
Oiiouui12 分钟前
linux服务器部署Logto后端与对应前端的实现
linux·服务器·前端·后端
字节跳动开源28 分钟前
OpenViking连接业务系统,LLM Wiki一键编译
数据库·开源
shenlongproxy42 分钟前
代理IP故障演练怎么做:注入怎么分档、恢复怎么判定
后端
知识搬运临时工42 分钟前
Kafka 发 1 GiB 数据,用户态 CPU 只花 0.016 秒,总耗时反而慢了 11%
后端·kafka
wt952742 分钟前
VMware 虚拟机磁盘扩容实战文档(Ubuntu 22.04 + LVM)
linux·后端
5233AI开发笔记42 分钟前
API 返回 429:先区分限速、并发和配额,再决定是否重试
python
Dovis(誓平步青云)42 分钟前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
databook42 分钟前
经常听到的透视表是干什么的?
python·数据分析·pandas
王中阳Go43 分钟前
预算给够了,时间花错了地方:三跳链路给了 27 秒,实际只用掉 9 秒
人工智能·后端·性能优化