我有这段现有的代码,用于将文件上传到我的 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,我使用该 URL 上传文件而不会出现任何问题。我已经添加了它的新用法,我正在上传 png,并且我已经很好地进行了上传到预签名网址的测试。问题是如果我去查看 s3 中的文件,我无法预览它。如果我下载它,它也不会打开。s3 Web 客户端显示它具有内容类型图像/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 而不是八位字节流,但我不确定我做错了什么.谷歌搜索这通常会导致人们遇到签名问题,因为没有正确设置或传递内容类型,我觉得我已经在这里有效地做到了这一点,如果我更改内容类型,一切都会失败。我猜我上传文件或读取文件以进行上传的方式有问题?
所以这与我上传的方式有关。因此,如果我像这样上传,它可以工作。
context.upload_signature_response = requests.put(response, data=open("features/steps/{}".format(signature_file_name), 'rb'), headers=headers)
所以这必须与put_object的使用有关。它必须期望正文是定义的内容类型的文件。此方法可以完成前一种方法使其成为多部分上传。所以我认为可以肯定地说,分段上传与put_object的预签名 URL 不兼容。
我仍然完全拼凑它,所以请随时填写空白。