Python 工具类实现大文件断点续传功能详解

Python 工具类实现大文件断点续传功能详解

简介

在文件上传或下载过程中,如果遇到大文件,如果发生传输失败,需要重新传输的情况会非常不方便,甚至无法实现。为了解决这种问题,我们可以实现大文件断点续传功能,使文件上传或下载可以随时中断和恢复。

实现流程

大文件断点续传的实现流程如下:

  1. 设置支持 range 的Range头,支持服务器返回指定范围的数据。

  2. 获取已下载或已上传的文件大小,作为Range头的值发送给服务器。

  3. 将请求的数据写入到文件中,同时记录已下载或已上传的文件大小,作为下次请求的Range头的值。

  4. 如果请求发生中断,下次请求的Range头的值应为已下载或已上传的文件大小。

  5. 下一次请求时,从已下载或已上传的文件大小处开始请求即可。

示例说明

下面分两个示例说明大文件断点续传功能的实现。

示例1:大文件上传

在文件上传过程中,如果上传过程中出现中断,可以实现大文件上传的断点续传功能。

import requests

class FileUploader():
    def __init__(self, url):
        self.url = url
        self.chunk_size = 1024*1024*10

    def upload(self, file_path):
        with open(file_path, 'rb') as f:
            size = os.path.getsize(file_path)
            start = 0
            # 读取上次上传的位置
            if os.path.exists(f'{file_path}.cur'):
                with open(f'{file_path}.cur', 'r') as cf:
                    start = int(cf.read())
            f.seek(start)
            while start < size:
                end = min(start + self.chunk_size, size)
                data = f.read(self.chunk_size)
                headers = {'Content-Range': f'bytes {start}-{end-1}/{size}'}
                response = requests.put(self.url, headers=headers, data=data)
                if response.status_code == 200 or response.status_code == 201:
                    # 保存上传位置
                    with open(f'{file_path}.cur', 'w') as cf:
                        cf.write(str(end))
                    start = end
                else:
                    print(f'Error! status_code: {response.status_code}')

if __name__ == '__main__':
    uploader = FileUploader('http://xxx.com/file')
    uploader.upload('bigfile.zip')

上述代码中,我们定义了一个 FileUploader 类,其中 chunk_size 表示单次上传的大小,文件上传的范围使用 Content-Range 头指定,上传前先读取上次上传的位置,然后将已上传的位置写入到文件中。

示例2:大文件下载

在文件下载过程中,如果下载过程中出现中断,可以实现大文件下载的断点续传功能。

import requests
import os

class FileDownloader():
    def __init__(self, url, file_path):
        self.url = url
        self.file_path = file_path
        self.chunk_size = 1024*1024*10

    def download(self):
        headers = {}
        if os.path.exists(self.file_path):
            start = os.path.getsize(self.file_path)
            headers = {'Range': f'bytes={start}-'}
            print(f'Resumable mode: start download from {start}')
        else:
            start = 0
            print('Normal mode: start download from beginning')
        response = requests.get(self.url, headers=headers, stream=True)
        with open(self.file_path, 'ab') as f:
            total_size = int(response.headers.get('content-length', start))
            for chunk in response.iter_content(chunk_size=self.chunk_size):
                if chunk:
                    f.write(chunk)
                    f.flush()
            print('Download success!')

if __name__ == '__main__':
    downloader = FileDownloader('http://xxx.com/bigfile.zip', 'bigfile.zip')
    downloader.download()

上述代码中,我们定义了一个 FileDownloader 类,其中文件下载的范围使用 Range 头指定,下载前先读取已下载的文件大小,然后使用追加模式打开文件,将读取到的数据写入到文件中。

完整代码

将以上两个示例整合起来,我们可以实现大文件的断点续传功能。

import requests
import os

class FileUploader():
    def __init__(self, url):
        self.url = url
        self.chunk_size = 1024*1024*10

    def upload(self, file_path):
        with open(file_path, 'rb') as f:
            size = os.path.getsize(file_path)
            start = 0
            # 读取上次上传的位置
            if os.path.exists(f'{file_path}.cur'):
                with open(f'{file_path}.cur', 'r') as cf:
                    start = int(cf.read())
            f.seek(start)
            while start < size:
                end = min(start + self.chunk_size, size)
                data = f.read(self.chunk_size)
                headers = {'Content-Range': f'bytes {start}-{end-1}/{size}'}
                response = requests.put(self.url, headers=headers, data=data)
                if response.status_code == 200 or response.status_code == 201:
                    # 保存上传位置
                    with open(f'{file_path}.cur', 'w') as cf:
                        cf.write(str(end))
                    start = end
                else:
                    print(f'Error! status_code: {response.status_code}')

class FileDownloader():
    def __init__(self, url, file_path):
        self.url = url
        self.file_path = file_path
        self.chunk_size = 1024*1024*10

    def download(self):
        headers = {}
        if os.path.exists(self.file_path):
            start = os.path.getsize(self.file_path)
            headers = {'Range': f'bytes={start}-'}
            print(f'Resumable mode: start download from {start}')
        else:
            start = 0
            print('Normal mode: start download from beginning')
        response = requests.get(self.url, headers=headers, stream=True)
        with open(self.file_path, 'ab') as f:
            total_size = int(response.headers.get('content-length', start))
            for chunk in response.iter_content(chunk_size=self.chunk_size):
                if chunk:
                    f.write(chunk)
                    f.flush()
            print('Download success!')

if __name__ == '__main__':
    uploader = FileUploader('http://xxx.com/file')
    uploader.upload('bigfile.zip')

    downloader = FileDownloader('http://xxx.com/bigfile.zip', 'bigfile.zip')
    downloader.download()

结论

大文件断点续传的实现思路简单,但需要注意多线程、分块的上传下载原理以及网络请求出现错误的情况,这些都需要人为处理并产生合理的错误反馈。通过使用断点续传技术,我们可以优化文件上传和下载,增强用户体验,提升系统稳定性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 工具类实现大文件断点续传功能详解 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • 在Python程序和Flask框架中使用SQLAlchemy的教程

    以下是关于在Python程序和Flask框架中使用SQLAlchemy的完整攻略。 一、什么是SQLAlchemy SQLAlchemy 是一个 Python 的 SQL 工具和 ORM 框架。它通过 SQL 表达式和对象关系映射来支持数据库交互。 它提供了一致的 SQL 表达式语言,以及自定义对象关系映射(ORM)APIs。 二、在Python程序中使用S…

    Flask 2023年5月15日
    00
  • Python Flask基础到登录功能的实现代码

    我来详细讲解一下“Python Flask基础到登录功能的实现代码”的完整攻略,以下是详细步骤: 1.安装 Flask 首先,在命令行中使用pip安装Flask: $ pip install Flask 2.创建 Flask 应用 在一个新的Python文件中,导入Flask库,然后使用Flask()构造函数创建一个新的应用 from flask impor…

    Flask 2023年5月15日
    00
  • Flask response 对象详情

    Flask框架中的response对象是HTTP响应的一部分,它代表了服务器返回给客户端的的数据。在Flask中,response对象包含响应体、HTTP状态码、消息头等信息。让我们来仔细了解Flask response对象的详细内容。 响应体 响应体指的是返回给客户端的实际数据。可以通过app.route()装饰器的返回值来设置响应体。响应体可以是字符串,…

    Flask 2023年5月16日
    00
  • Flask如何接收前端ajax传来的表单(包含文件)

    要让Flask能够接收前端Ajax传来的表单数据(包括文件),需要注意以下几个步骤: 在前端使用ajax请求时,需要将请求内容以FormData的形式打包,以支持传输文件。 在Flask后端,需要使用request.form和request.files两个对象分别获取表单字段和文件数据。 某些情况下,上传文件时需要设置Flask应用程序的配置,以支持文件上传…

    Flask 2023年5月16日
    00
  • Python+ Flask实现Mock Server详情

    下面是Python + Flask实现Mock Server的完整攻略: 1. 什么是Mock Server Mock Server是指一个虚拟的服务端,用于模拟实际的服务端行为以便进行测试和开发。通过构建Mock Server,我们可以在没有实际服务端的情况下进行开发和测试,从而提高开发效率。 2. Flask框架简介 Flask是一个轻量级的Web框架,…

    Flask 2023年5月15日
    00
  • 使用python为mysql实现restful接口

    让我为您介绍使用Python为MySQL实现RESTful接口的完整攻略,包括两个示例说明。 环境准备 在开始这个过程之前,您必须确保以下组件已经被正确安装在您的计算机上: Python 3.6 或更高版本 (可以从官方网站下载) Flask 框架 (可以使用 pip install flask 命令安装) mysql-connector-python 模块…

    Flask 2023年5月16日
    00
  • Python中的flask框架详解

    Flask框架详解 Flask是一个基于Python语言的Web应用程序框架,由于其轻量、易学易用、灵活性强、完美与其他框架协作等特性,已经成为Python开发中最为流行的Web框架之一。下面详细讲解一下Flask框架的组成以及其常用的功能模块。 1.1 组成 Flask框架的核心组件包括:路由、请求上下文、应用上下文、视图函数、JSON支持、请求-响应对象…

    Flask 2023年5月15日
    00
  • Flask搭建一个API服务器的步骤

    下面我将详细讲解使用Flask框架搭建API服务器的步骤。 简介 Flask 是一个“微型”Python Web框架。它非常简单易学且具有高度的灵活性。本文将介绍如何使用 Flask 框架搭建一个API服务器。 步骤 1. 安装 Flask 在开始之前,请确保您的电脑上已经安装了 Python 3.x,并且安装了 Flask 框架。您可以使用以下命令安装 F…

    Flask 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部