gpt4 book ai didi

python - cherrypy中的大文件下载

转载 作者:行者123 更新时间:2023-11-28 21:53:30 26 4
gpt4 key购买 nike

我在 Raspberry Pi 上通过 uwsgi 和 nginx 使用 Cherrypy 托管一个文件访问类型的网站。我注意到的一件事是,如果文件相当大(比方说,大约 1 GB),uwsgi 说它被信号 9 杀死。这是通过放置 cherrypy.config.update({'tools .sessions.timeout': 1000000}) 但这并不能真正解决问题,因为它是一个糟糕的 hacky 解决方法,实际上并没有用。它主要只是通过使超时非常大而导致另一个问题。此外,浏览器无法非常准确地估计需要多长时间,最终会挂起一段时间(阅读:在有线连接上大约 5 分钟),然后快速开始下载。

它开始于

The file download

然后去

The continued file download

我的下载代码很简单,只有这一行。

return cherrypy.lib.static.serve_file(路径,"application/x-download",os.path.basename(path))

我以前的下载代码运行得不太好。


f = 文件(路径)
cherrypy.response.headers['Content-Type'] = getType(path)[0]
返回 f
有办法解决这个问题吗?

最佳答案

一般考虑

首先,我不得不说这是一个堆积如山的配置,CherryPy -> uWSGI -> Nginx,对于这样一个受限环境。 According to the author , 在没有特殊要求的情况下,将 CherryPy 单独用于小型应用程序是安全的。在前面添加 Nginx 增加了很多灵 active ,因此通常是有益的,但只要 CherryPy 的默认部署是标准 HTTP,我强烈建议保留两者(并且完全忘记 WSGI)。

其次,考虑到您尝试过的解决方法,您可能已经知道您的问题可能与 session 相关。这是 the quote来自有关文件下载的流媒体响应主体的文档。

In general, it is safer and easier to not stream output. Therefore, streaming output is off by default. Streaming output and also using sessions requires a good understanding of how session locks work.

它建议的是手动 session 锁定管理。了解您的应用程序的工作原理应该会引导您进行适当的锁设计。

第三个。通常有一种方法可以将处理文件下载的职责转移到 Web 服务器,基本上是通过从代理应用程序发送带有文件名的适当 header 。如果在 nginx 上它叫做 X-accel .因此,您可以避免锁定管理的麻烦,同时仍然有 session 限制下载。

实验

我制作了一个简单的 CherrPy 应用程序,带有两个下载选项,并将其置于 Nginx 之后。我在 FirefoxChromium 中的本地 Linux 机器上播放了 1.3GiB 视频文件。共有三种方式:

  1. 从 CherryPy 免代理下载 (http://127.0.0.1:8080/native/video.mp4),
  2. 通过 Nginx 从 CherryPy 代理下载(http://test/native/video.mp4),
  3. 通过 Nginx 从 CherryPy 下载 X-accel (http://test/nginx/video.mp4)。

对于 (1) 和 (2),我在 Firefox 和 Chromium 中都有轻微的奇怪行为。 (1) 在 Firefox 上,正常运行时间为几天,我一直拥有 ~5MiB/s 的下载速度和一个满载的 CPU 内核。在新鲜的 Firefox 上没有这样的行为。 (2) 在 Chromium 上导致了几个未完成的中断下载(所有时间都在 1GiB 左右)。但总的来说,这两种浏览器都显示了大约 50-70MiB/s 的 HDD 物理性能。

对于 (3) 我在这两个方面都没有问题,相同的 50-70MiB/s 吞吐量,所以不知何故在我的小实验中它最终成为最稳定的方式。

设置

app.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import os

import cherrypy


DownloadPath = '/home/user/Videos'

config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}


class App:

@cherrypy.expose
def index(self):
return 'Download test'

@cherrypy.expose
def native(self, name):
basename = os.path.basename(name)
filename = os.path.join(DownloadPath, basename)
mime = 'application/octet-stream'
return cherrypy.lib.static.serve_file(filename, mime, basename)

@cherrypy.expose
def nginx(self, name):
basename = os.path.basename(name)
cherrypy.response.headers.update({
'X-Accel-Redirect' : '/download/{0}'.format(basename),
'Content-Disposition' : 'attachment; filename={0}'.format(basename),
'Content-Type' : 'application/octet-stream'
})


if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)

app.conf

server {
listen 80;

server_name test;

root /var/www/test/public;

location /resource {
# static files like images, css, js, etc.
access_log off;
}

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location /download {
internal;
alias /home/user/Videos;
}

}

关于python - cherrypy中的大文件下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26227727/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com