首页 > 解决方案 > S3 对象返回八位字节流,但上传为 png

问题描述

我有这段现有的代码,用于将文件上传到我的 s3 存储桶。

def get_user_upload_url(customer_id, filename, content_type):
    s3_client = boto3.client('s3')
    object_name = "userfiles/uploads/{}/{}".format(customer_id, filename)
    try:
        url = s3_client.generate_presigned_url('put_object',
                                                    Params={'Bucket': BUCKET,
                                                            'Key': object_name,
                                                            "ContentType": content_type # set to "image/png"
                                                            },
                                                    ExpiresIn=100)
    except Exception as e:
        print(e)
        return None

    return url

这会向我的客户返回一个预签名的 URL,我可以使用它毫无问题地上传我的文件。我在上传 png 的地方添加了它的新用途,并且我已经进行了上传到预签名 url 的行为测试。问题是如果我去查看 s3 中的文件,我无法预览它。如果我下载它,它也不会打开。s3 Web 客户端显示它具有 Content-Type image/png。我视觉比较了原始文件和下载文件的二进制文件,我可以看到差异。文件类型工具检测到它是八位字节流。

    signature_file_name = "signature.png"
    with open("features/steps/{}".format(signature_file_name), 'rb') as f:
        files = {'file': (signature_file_name, f)}
        headers = {
            'Content-Type': "image/png" # without this or with a different value the presigned url will error with a signatureDoesNotMatch
        }
        context.upload_signature_response = requests.put(response, files=files, headers=headers)

我本来希望返回的是 PNG 而不是八位字节流,但是我不确定我做错了什么。谷歌搜索这通常会导致人们在签名时遇到问题,因为没有正确设置或传递内容类型,我觉得我已经有效地做到了这一点,事实证明如果我更改内容类型一切都会失败。我猜我上传文件的方式有问题,或者可能是读取文件以进行上传?

标签: pythonamazon-s3boto3

解决方案


所以这与我如何上传有关。因此,如果我像这样上传,它会起作用。

context.upload_signature_response = requests.put(response, data=open("features/steps/{}".format(signature_file_name), 'rb'), headers=headers)

所以这一定与put_object的使用有关。它必须期望正文是已定义内容类型的文件。此方法完成了前一个方法将其设为多部分上传的位置。所以我认为可以肯定地说分段上传与 put_object 的预签名 URL 不兼容。

我仍然在拼凑它,所以请随意填写空白。


推荐阅读