Pythonでダウンロード機能をコーディングしています。ファイルサイズが 1GB を超えています。サーバーは Linux、HTTP サーバーは Karrigell です。クライアントはブラウズ、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
今回は、サーバーメモリはOKですが、ブラウズダイ!ブラウズ メモリが急速に上昇します。ソケットがファイル コンテンツ全体を受け入れるまで解放されません。
これらの問題に対処する方法がわかりません。2 番目のアイデアは正しいと思います。コンテンツをソケットに直接送信します。しかし、データを受け入れている間、ブラウズでメモリを解放できないのはなぜでしょうか?