2009-11-25 44 views
20

Có cách nào để tải xuống tệp lớn và vẫn đang phát triển qua HTTP bằng tính năng tải xuống một phần không?Tải xuống tệp bằng cách sử dụng tải xuống một phần (HTTP)

Có vẻ như rằng mã này tải tập tin từ đầu mỗi khi nó thực hiện:

import urllib 
urllib.urlretrieve ("http://www.example.com/huge-growing-file", "huge-growing-file") 

tôi muốn:

  1. Để lấy chỉ là dữ liệu mới được viết
  2. Tải về từ đầu chỉ khi tệp nguồn trở nên nhỏ hơn (ví dụ: tệp đã được xoay).

Trả lời

40

Có thể làm một phần tải về sử dụng tiêu đề phạm vi, sau đây sẽ yêu cầu một phạm vi lựa chọn của byte:

req = urllib2.Request('http://www.python.org/') 
req.headers['Range'] = 'bytes=%s-%s' % (start, end) 
f = urllib2.urlopen(req) 

Ví dụ:

>>> req = urllib2.Request('http://www.python.org/') 
>>> req.headers['Range'] = 'bytes=%s-%s' % (100, 150) 
>>> f = urllib2.urlopen(req) 
>>> f.read() 
'l1-transitional.dtd">\n\n\n<html xmlns="http://www.w3.' 

Sử dụng tiêu đề này, bạn có thể tiếp tục tải xuống một phần. Trong trường hợp của bạn, tất cả những gì bạn phải làm là theo dõi kích thước đã tải xuống và yêu cầu một phạm vi mới.

Hãy nhớ rằng máy chủ cần chấp nhận tiêu đề này để hoạt động.

+2

Ngoài ra, bạn phải kiểm tra tiêu đề Phạm vi nội dung (có thể khác với phạm vi bạn yêu cầu) và có thể sẵn sàng phân tích cú pháp nội dung nhiều phần/byterang. –

+2

Kiểm tra khía cạnh đa điểm/byterang. Thông số kỹ thuật rõ ràng không cho phép phản hồi nhiều phần/byteranges với một yêu cầu phạm vi duy nhất. –

+2

Để lấy phần còn lại từ một vị trí trên (một trường hợp điển hình), chỉ cần sử dụng '" bytes =% d- "' (i. E. Không có giá trị kết thúc). – Alfe

0

Nếu tôi hiểu chính xác câu hỏi của bạn, tệp sẽ không thay đổi trong quá trình tải xuống nhưng được cập nhật thường xuyên. Nếu đó là câu hỏi, rsync là câu trả lời.

Nếu tệp đang được cập nhật liên tục kể cả trong khi tải xuống, bạn cần sửa đổi rsync hoặc chương trình bittorrent. Họ chia các tệp thành các phần riêng biệt và tải xuống hoặc cập nhật các khối độc lập. Khi bạn đến cuối tập tin từ lần lặp đầu tiên, lặp lại để lấy đoạn được nối thêm; tiếp tục khi cần thiết. Với ít hiệu quả hơn, người ta có thể lặp lại nhiều lần.

+1

có yêu cầu đối với HTTP nên rsync không phải là câu trả lời hợp lệ –

2

Điều này khá dễ thực hiện khi sử dụng các cổng TCP và HTTP thô. Tiêu đề yêu cầu có liên quan là "Phạm vi".

Một yêu cầu ví dụ có thể trông giống như:

mysock = connect(("www.example.com", 80)) 
mysock.write(
    "GET /huge-growing-file HTTP/1.1\r\n"+\ 
    "Host: www.example.com\r\n"+\ 
    "Range: bytes=XXXX-\r\n"+\ 
    "Connection: close\r\n\r\n") 

đâu XXXX đại diện cho số byte bạn đã lấy ra. Sau đó, bạn có thể đọc các tiêu đề phản hồi và bất kỳ nội dung nào từ máy chủ. Nếu máy chủ trả về tiêu đề như:

Content-Length: 0 

Bạn biết bạn đã có toàn bộ tệp.

Nếu bạn muốn đặc biệt tốt đẹp như một ứng dụng khách HTTP, bạn có thể xem "Kết nối: tiếp tục sống". Có lẽ có một thư viện python mà làm tất cả mọi thứ tôi đã mô tả (có lẽ ngay cả urllib2 hiện nó!) Nhưng tôi không quen thuộc với một.

+1

Xem câu trả lời của Nadia Alramli. –

+1

Nếu bạn cuộn giải pháp của riêng mình bằng các cổng TCP thì bạn sẽ loại bỏ tất cả các tính năng trong urllib2, như chuyển hướng sau và xử lý cài đặt proxy. –

+0

Tuyệt đối. Tôi không nhớ urllib2 hỗ trợ thiết lập các tiêu đề Yêu cầu tùy ý. Đó là (tất nhiên) đúng cách để đi đây. –

Các vấn đề liên quan