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日

相关文章

  • Flask-Sqlalchemy的基本使用详解

    下面是关于”Flask-Sqlalchemy的基本使用详解”的完整攻略,包括两个示例说明。 什么是Flask-Sqlalchemy Flask-Sqlalchemy是Flask框架中的一个扩展,其提供了对SQLAlchemy ORM的集成支持。其主要提供了以下功能: 方便地在Flask应用程序中使用数据库。 管理数据库模型,自动生成SQL语句。 安装Flas…

    Flask 2023年5月15日
    00
  • 使用python+Flask实现日志在web网页实时更新显示

    使用Python+Flask实现日志在Web网页实时更新显示的过程可以分为以下几步: 安装Flask和WebSocket 在命令行中执行以下命令,安装Flask和WebSocket: pip install flask pip install flask-socketio 创建Flask应用 创建一个Python脚本文件,命名为app.py,代码如下: fr…

    Flask 2023年5月16日
    00
  • flask上使用websocket的方法示例

    下面是关于“flask上使用websocket的方法示例”的完整攻略。 什么是WebSocket? WebSocket是一种基于TCP协议的新型网络通信协议,相比HTTP协议,它具有以下优点: 长连接:WebSocket是一种长连接,可以实时的双向通讯,我们不需要反复的建立连接和释放连接,节省了很多浏览器和服务器的开销。 实时性:WebSocket具有实时通…

    Flask 2023年5月16日
    00
  • js实现录音上传功能

    下面我会为你详细讲解如何使用JS实现录音上传功能。 背景介绍 录音上传功能是一种常见的Web应用程序功能,它可以使用户在Web端录制音频并将其上传到服务器上。这种功能可以用于许多应用,比如在线音乐教育、在线语音识别、在线语音聊天等等。 实现录音上传功能需要使用Web开发中的一种技术,Web Audio API。Web Audio API提供了一个丰富、强大的…

    Flask 2023年5月16日
    00
  • Python Flask中Cookie和Session区别详解

    下面我为你详细讲解“Python Flask中Cookie和Session区别详解”的攻略,包含两个示例说明。 Cookie和Session的基本概念 在Flask开发中,Cookie和Session是两个经常使用的概念。Cookie是保存在客户端的记录,而Session是保存在服务器端的记录,通过Cookie来实现客户端和服务器端之间的信息传递。 Cook…

    Flask 2023年5月16日
    00
  • python flask解析json数据不完整的解决方法

    Python Flask解析JSON数据不完整的解决方法 在Python Flask中,我们经常需要使用JSON格式来处理数据交互。然而,在解析JSON数据时有时会出现数据不完整的情况,可能会导致程序出错。在本篇文章中,我们将学习如何解析JSON数据不完整的问题,并给出两个示例进行说明。 解析JSON数据不完整的原因 在使用Python Flask框架解析J…

    Flask 2023年5月16日
    00
  • jsp留言板源代码四: 给jsp初学者.

    下面就详细讲解“jsp留言板源代码四: 给jsp初学者.”的攻略。 前言 “jsp留言板源代码四: 给jsp初学者.”是一份用于帮助初学jsp的开发者,快速掌握jsp留言板开发的源代码。本攻略将详细介绍如何运行该源代码,并对其中两条示例进行说明。 运行源代码 运行jsp留言板源代码前,需要先确保本地电脑已经安装了Java和Tomcat环境。接下来,按照以下步…

    Flask 2023年5月16日
    00
  • Python Flask框架模板操作实例分析

    Python Flask框架模板操作实例分析 什么是Python Flask框架模板操作? 在使用 Flask 编写 Web 应用程序时,我们通常需要动态生成 HTML 页面。这可以通过 Flask 框架内置的模板引擎来实现。模板引擎是一个将数据和模板进行对比并渲染到页面上的工具。它可以使用类似于 Python 的语法和一些基本控制结构(例如 if 语句、f…

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