gpt4 book ai didi

python - 如何在python中以二进制模式下载大文件?

转载 作者:太空宇宙 更新时间:2023-11-03 19:32:34 25 4
gpt4 key购买 nike

我正在用Python编写一个下载功能。文件大小>1GB。服务器是linux,HTTP服务器是Karrigel。客户端是浏览器、Firefox 或 IE。我遇到了一个大麻烦。

首先,我使用 sys.stdout() 发送文件内容。

file = open(path, 'rb')
size = os.path.getsize(path)

RESPONSE['Pragma'] = 'public'
RESPONSE['Expires'] = '0'
RESPONSE['Cache-Control'] = 'must-revalidate, pre-check=0'
RESPONSE['Content-Disposition'] = 'attachment; filename="' + os.path.basename(path) + '"'
RESPONSE['Content-type'] = "application/octet-stream"
RESPONSE['Content-Transfer-Encoding'] = 'binary'
RESPONSE['Content-length'] = str(os.path.getsize(path))

sys.stdout.flush()
chunk_size = 10000
handle = open(path, "rb")
while True:
buffer = handle.read(chunk_size)
if buffer:
STDOUT(buffer)
else:
break
sys.stdout.flush()

问题是服务器内存不足!我知道,stdout 首先将内容写入内存,然后内存发送到套接字。

所以,我修改了这个函数。直接将内容发送到套接字。我使用 py-sendfile 模块。 http://code.google.com/p/py-sendfile/

file = open(path, 'rb')
size = os.path.getsize(path)

sock = REQUEST_HANDLER.sock
sock.sendall("""HTTP/1.1 200 OK\r\nPragma: no-cache\r\nExpires: 0\r\nCache-Control: no-cache, no-store\r\nContent-Disposition: attachment; filename="%s"\r\nContent-Type: application/octet-stream\r\nContent-Length: %u\r\nContent-Range: bytes 0-4096/%u\r\nLocation: "%s"\r\n\r\n""" % (os.path.basename(path), size, size, os.path.basename(path)))

offset = 0
nbytes = 4096
while 1:
try:
sent = sendfile.sendfile(sock.fileno(), file.fileno(), offset, nbytes)
except OSError, err:
if err.errno in (errno.EAGAIN, errno.EBUSY): # retry
continue
raise
else:
if sent == 0:
break # done
offset += sent

这次,服务器内存没问题,但是浏览死了!浏览内存快速上升!不免费直到套接字接受整个文件内容。

我不知道如何处理这些问题。我认为第二种想法是对的,直接将内容发送到socket。但为什么浏览器在接受数据时不能释放内存呢?

最佳答案

您应该尝试分块下载文件。这是一个使用 urllib2 对我有用的示例

import os
import urllib2
import math

def downloadChunks(url):
"""Helper to download large files
the only arg is a url
this file will go to a temp directory
the file will also be downloaded
in chunks and print out how much remains
"""

baseFile = os.path.basename(url)

#move the file to a more uniq path
os.umask(0002)
temp_path = "/tmp/"
try:
file = os.path.join(temp_path,baseFile)

req = urllib2.urlopen(url)
total_size = int(req.info().getheader('Content-Length').strip())
downloaded = 0
CHUNK = 256 * 10240
with open(file, 'wb') as fp:
while True:
chunk = req.read(CHUNK)
downloaded += len(chunk)
print math.floor( (downloaded / total_size) * 100 )
if not chunk: break
fp.write(chunk)
except urllib2.HTTPError, e:
print "HTTP Error:",e.code , url
return False
except urllib2.URLError, e:
print "URL Error:",e.reason , url
return False

return file

关于python - 如何在python中以二进制模式下载大文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5064879/

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