aliyun / aliyun-oss-python-sdk

Aliyun OSS SDK for Python
MIT License
931 stars 363 forks source link

使用OSS2 Client下载content-encoding: gzip文件时会报错 #362

Open shikaiwei1 opened 12 months ago

shikaiwei1 commented 12 months ago

基础信息

复现方式:

  1. 准备一个文本文档,通过代码将该文本通过gzip组件压缩,将压缩后的bytes通过OSS客户端存入bucket,并指定headers:{"Content-Encoding":"gzip"}
  2. 通过当前版本(包括当前最新版本)的PYTHON SDK,下载改文件
oss_client.get_object_to_file(object_key, file_path) 
  1. 得到报错:
{
    "message":"{'status': -3, 'x-oss-request-id': '65095A3203B7CC3739039AF6', 'details': 'InconsistentError: IncompleteRead from source'}",
    "stack":[
        "  File "/home/app/xxx/index.py", line 296, in root
    return invoke(environ, start_response)
",
        "  File "/home/app/xxx/index.py", line 254, in invoke
    ret = handler_srm_create_object(evt['data'], context)
",
        "  File "/home/app/xxx/index.py", line 111, in handler_srm_create_object
    oss_client.get_object_to_file(object_key, file_path)
",
        "  File "/usr/lib/python3.10/site-packages/oss2/api.py", line 828, in get_object_to_file
    utils.copyfileobj_and_verify(result, f, result.content_length, request_id=result.request_id)
",
        "  File "/usr/lib/python3.10/site-packages/oss2/utils.py", line 863, in copyfileobj_and_verify
    raise InconsistentError("IncompleteRead from source", request_id)
"
    ]
}

原因分析

在oss2/api.py文件的68行,判断是否存在content_length,存在的情况下会进入到71行,调用下列方法:

utils.copyfileobj_and_verify(result, f, result.content_length, request_id=result.request_id)

该方法通过result.read方法读取的实际文件大小会!=content_length,导致报错。

实际文件大小!=content_length的原因: 由于对象文件的"Content-Encoding":"gzip",http组件会自动对其进行解压缩,而headers中的content_length大小为其解压缩前的大小,最终导致该问题。

解决方案:

判断Content-Encoding!=压缩类型的格式(gzip\br)再调用copyfileobj_and_verify方法