Python-Breakpoint-Download-Datei

Verwenden Sie Python-Codierung, um den Breakpoint-Download von Dateien zu implementieren

import os
import json
import hashlib
import logging
import requests
import traceback
from contextlib import closing

logger = logging.getLogger()


def download_file(url, save_file_path, new_file_name):
    """
    下载文件
    :param url: 目标文件 url
    :param save_file_path: 本地保存下载文件的路径
    :param new_file_name: 文件名称

    :return: (status, md5, msgs)
    :rtype: status INT, 0: 下载成功, -1:下载失败
    :rtype: md5 STRING, 下载成功返回 md5 值,否则返回 None
    :rtype: msgs STRING, 对下载结果的描述信息
    """
    logger.info(f"Start to download file, url: {
      
      url}")
    try:
        os.mkdir(save_file_path)
    except FileExistsError:
        pass
    except FileNotFoundError:
        os.makedirs(save_file_path)
    file_content = bytearray()
    try:
        with closing(requests.get(url=url, stream=True)) as res:
            if res.status_code != 200:
                return -1, None, res.text
            try:
                json_res = json.loads(res.content)
                message = f"Download file failed, code: {
      
      json_res.get('code')}, msg: {
      
      json_res.get('msg')}"
                logger.error(message)
                return -1, None, message
            except Exception:
                with open(save_file_path + new_file_name, 'wb') as fd:
                    for chunk in res.iter_content(chunk_size=1024):
                        if chunk:
                            fd.write(chunk)
                            file_content.extend(chunk)
        hash_obj = hashlib.md5()
        hash_obj.update(file_content)
        logger.info(f"End to download file, url: {
      
      url}, filename: {
      
      new_file_name}")
        return 0, hash_obj.hexdigest(), "Success"
    except Exception as e:
        logger.error(traceback.format_exc())
        return -1, None, str(e)


def breakpoint_download_file(file_url, file_dir, new_file_name):
    """断点续传下载文件"""
    logger.info(f"Start breakpoint download file, file_url: {
      
      file_url}")
    try:
        os.mkdir(file_dir)
    except FileExistsError:
        pass
    except FileNotFoundError:
        os.makedirs(file_dir)

    # 设置 headers,检查文件下载进度
    file_path = file_dir + new_file_name
    if os.path.exists(file_path):
        start_byte = os.path.getsize(file_path)
    else:
        start_byte = 0

    headers = {
    
    'Range': f'bytes={
      
      start_byte}-'}
    # 发送 GET 请求
    try:
        with closing(requests.get(url=file_url, stream=True, headers=headers)) as res:
            # 206表示该服务器已经成功处理了部分 GET 请求
            if res.status_code not in [200, 206]:
                return -1, None, res.text

            # 获取总字节数,计算出剩余未下载的字节数
            total_size = int(res.headers.get('content-length', 0))
            remaining_bytes = total_size - start_byte

            # 写入文件
            with open(file_path, 'ab') as f:
                for chunk in res.iter_content(chunk_size=1024):
                    # 如果已经下载完成,退出循环
                    if remaining_bytes <= 0:
                        break

                    # 计算本次需要写入的字节数
                    bytes_to_write = len(chunk)
                    if bytes_to_write > remaining_bytes:
                        bytes_to_write = remaining_bytes

                    # 写入文件并更新记录
                    f.write(chunk[:bytes_to_write])
                    remaining_bytes -= bytes_to_write

        # 以二进制只读方式打开文件并计算 MD5 校验和
        # 以二进制只读方式打开文件并计算 MD5 校验和
        with open(file_path, 'rb') as f:
            md5_hash = hashlib.md5()
            chunk = f.read(8192)
            while chunk:
                md5_hash.update(chunk)
                chunk = f.read(8192)

        logger.info(f"End to download file, url: {
      
      file_url}, filepath: {
      
      file_path}, "
                    f"filesize: {
      
      os.path.getsize(file_path)}, md5: {
      
      md5_hash.hexdigest()}")
        return 0, md5_hash.hexdigest(), "Success"
    except Exception as e:
        logger.error(traceback.format_exc())
        return -1, None, str(e)

# if __name__ == '__main__':
#     breakpoint_download_file(
#         file_url="https://yos.yingzi.com/prod-bucket-iot/prod-iot-storage/1082233093836513280/MW301_ver2.2.30.ota",
#         file_dir='./', new_file_name="MW301_MW301_2.2.30.ota")

Guess you like

Origin blog.csdn.net/qq_38923792/article/details/130200460