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

相关推荐
秋田君几秒前
QT_一个UDP通信程序(单播+广播)
开发语言·qt·udp
a-6266 分钟前
三维重建的步骤-1(采集的是环绕物体均匀旋转一圈的视频)
python·pycharm·三维重建·metashape
IT_陈寒9 分钟前
Vite热更新失效?八成是这个配置在搞鬼
前端·人工智能·后端
龙腾AI白云11 分钟前
世界模型与大模型的区别
机器学习·知识图谱·pygame
cmes_love16 分钟前
期货五档Level2行情数据和分钟历史行情数据下载分析
数据库
qq_225891746618 分钟前
基于Flask的空气质量监测与预测分析系统
开发语言·后端·python·信息可视化·django·flask
某不知名網友21 分钟前
MySQL数据库库级操作|创建、字符集、修改删除、备份恢复
数据库·mysql
lhldsg32 分钟前
社区健身系统开发实战:从需求分析到落地部署全流程指南
java·开发语言·小程序·需求分析
李高钢33 分钟前
C# WPF Prism 进阶(三):导航(Navigation)深入
开发语言·c#·wpf
冯汉栩34 分钟前
Swift Control DashLineView(虚线)
开发语言·ios·swift