问题 如何在Python中恢复文件下载?


我正在使用python 2.7请求模块使用以下代码下载二进制文件,如何使此代码从部分下载的文件中“自动恢复”下载。

r = requests.get(self.fileurl, stream=True,  verify=False, allow_redirects=True)
if r.status_code == 200:
    CHUNK_SIZE = 8192
    bytes_read = 0
    with open(FileSave, 'wb') as f:
        itrcount=1
        for chunk in r.iter_content(CHUNK_SIZE):
            itrcount=itrcount+1
            f.write(chunk)
            bytes_read += len(chunk)
            total_per = 100 * float(bytes_read)/float(long(audioSize)+long(videoSize))


            self.progress_updates.emit('%d\n%s' % (total_per, 'Download Progress : ' + self.size_human(itrcount*CHUNK_SIZE) + '/' + Total_Size))
r.close()

我更愿意只使用 requests 如果可能的话,实现这个目标


11865
2018-04-06 12:44


起源



答案:


如果Web服务器支持范围请求,则可以将Range标头添加到您的请求中:

Range: bytes=StartPos-StopPos

您将收到StartPos和StopPos之间的部分。如果不知道StopPos只是使用:

Range: bytes=StartPos-

所以你的代码是:

def resume_download(fileurl, resume_byte_pos):
    resume_header = {'Range': 'bytes=%d-' % resume_byte_pos}
    return requests.get(fileurl, headers=resume_header, stream=True,  verify=False, allow_redirects=True)

14
2018-04-06 13:46



您还需要将文件模式从“wb”更改为“ab”(要追加,否则您将覆盖已保存的部分)。 - m.kocikowski
为了将来参考,resume_byte_pos是文件的当前大小,还是文件的当前大小减1? - Klik
@Klik肯定不是当前文件大小减1 - 如果你下载了0个字节,那么你不想从-1开始:)索引从0开始,所以你应该发送当前文件大小作为起始字节。 - Piotr Dabkowski
例如,您使用Range标头请求字节0-2000000。然后,检查文件大小 from pathlib import Path; path = Path(..); print(path.stat().st_size 它返回2000001字节。您可以使用此数字作为Range标头来请求2000001 -...中的下一部分。 - brimborium


答案:


如果Web服务器支持范围请求,则可以将Range标头添加到您的请求中:

Range: bytes=StartPos-StopPos

您将收到StartPos和StopPos之间的部分。如果不知道StopPos只是使用:

Range: bytes=StartPos-

所以你的代码是:

def resume_download(fileurl, resume_byte_pos):
    resume_header = {'Range': 'bytes=%d-' % resume_byte_pos}
    return requests.get(fileurl, headers=resume_header, stream=True,  verify=False, allow_redirects=True)

14
2018-04-06 13:46



您还需要将文件模式从“wb”更改为“ab”(要追加,否则您将覆盖已保存的部分)。 - m.kocikowski
为了将来参考,resume_byte_pos是文件的当前大小,还是文件的当前大小减1? - Klik
@Klik肯定不是当前文件大小减1 - 如果你下载了0个字节,那么你不想从-1开始:)索引从0开始,所以你应该发送当前文件大小作为起始字节。 - Piotr Dabkowski
例如,您使用Range标头请求字节0-2000000。然后,检查文件大小 from pathlib import Path; path = Path(..); print(path.stat().st_size 它返回2000001字节。您可以使用此数字作为Range标头来请求2000001 -...中的下一部分。 - brimborium