Python 设置S3文件属性中元数据的Content-Encoding值

codeAB 2019-10-23

背景: 使用脚本从S3下载下来的CSV文件打开发现是乱码,但是在网页上面点击下载按钮下载后却能正常打开.

研究发现,在S3文件属性的元数据中有Content-Encoding值是gzip

浏览器下载的时候会识别这个值,然后在帮你自动减压后下载. 但是利用官方boto3包的download_fileobj()方法中,却无法指定对应的参数(不知道以后不会优化).

下载的话就比较简单了,下载后直接利用gzip解压后再处理数据即可.

import boto3
import gzip
import csv


s3 = boto3.client('s3')
bucket = 'my_bucket'
download_key = 'my.csv'
file_path = '/tmp/my.csv'

with open('/tmp/my.csv.gz', 'wb') as file_date:
    s3.download_fileobj(bucket, download_key, file_date)
g = gzip.GzipFile(mode="rb", fileobj=open('/tmp/my.csv.gz', 'rb'))
open(file_path, "wb").write(g.read())
csv_file_open = open(file_path, 'r')
csv_file = csv.reader(csv_file_open)

上传的我研究了好久.因为我发现upload_file()方法中也无法提供Content-Encoding参数,虽然我找到了ExtraArgs参数中可以添加Metadata的字段,然后发现这个是个自定义元数据用的.会自动转换成x-amz-meta-content-encoding.这就很扯淡了.

s3_resource.meta.client.upload_file(file_path, bucket, key, ExtraArgs={'Metadata': {'Content-Encoding': 'gzip'}})

进一步研究发现在copy_object()方法中ContentEncoding 参数才是真正用来设置S3文件属性的元数据中的Content-Encoding值.

所以有一种方法是先用uploadfile上传数据,然后在用copy_object()拷贝后修改Content-Encoding属性.(这样比较蛋疼)

最后发现put_object()方法也带有这个参数,这样的话我们可以利用put_object方法来操作.代码片段如下.自己先压缩好gzip文件.

f = open('/tmp/my_gz.csv', 'rb')
response = s3.put_object(Body=f, Bucket=bucket,  Key='my.csv', ContentEncoding='gzip')

相关推荐