如何使用boto3快速提取S3中的文件?

The*_*One 7 amazon-s3 amazon-web-services aws-lambda

我正在尝试找到一种动态提取S3中的.gz文件的方法,无需将其下载到本地,提取然后将其推回S3。

使用boto3 + lambda,我如何实现我的目标?

我没有在boto3文档中看到任何摘录部分。

Joh*_*ein 12

Amazon S3 是一种存储服务。没有内置的功能来操作文件的内容。

但是,您可以使用 AWS Lambda 函数从 S3 检索对象,解压缩它,然后再次上传内容备份。但是请注意,Lambda 的临时磁盘空间有 500MB 的限制,因此请避免解压过多数据。

您可以将 S3 存储桶配置为在存储桶中创建新文件时触发 Lambda 函数。然后,Lambda 函数将:

  • 使用boto3(假设你喜欢Python)下载新文件
  • 使用zipfilePython 库提取文件
  • 使用 boto3 上传结果文件

示例代码

import boto3

s3 = boto3.client('s3', use_ssl=False)
s3.upload_fileobj(
    Fileobj=gzip.GzipFile(
        None,
        'rb',
        fileobj=BytesIO(
            s3.get_object(Bucket=bucket, Key=gzip_key)['Body'].read())),
    Bucket=bucket,
    Key=uncompressed_key)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢您的回答。我不知道 Lambda 的临时空间是 500 MB。就我而言,那个空间太小了。我想我会用传统的方法。 (3认同)

Tod*_*nes 7

您可以使用BytesIO从S3流式传输文件,通过gzip运行该文件,然后通过upload_fileobj写入BytesIO 将其通过管道传输回S3 。

# python imports
import boto3
from io import BytesIO
import gzip

# setup constants
bucket = '<bucket_name>'
gzipped_key = '<key_name.gz>'
uncompressed_key = '<key_name>'

# initialize s3 client, this is dependent upon your aws config being done 
s3 = boto3.client('s3', use_ssl=False)  # optional
s3.upload_fileobj(                      # upload a new obj to s3
    Fileobj=gzip.GzipFile(              # read in the output of gzip -d
        None,                           # just return output as BytesIO
        'rb',                           # read binary
        fileobj=BytesIO(s3.get_object(Bucket=bucket, Key=gzipped_key)['Body'].read())),
    Bucket=bucket,                      # target bucket, writing to
    Key=uncompressed_key)               # target key, writing to
Run Code Online (Sandbox Code Playgroud)

确保您的密钥正在正确读取:

# read the body of the s3 key object into a string to ensure download
s = s3.get_object(Bucket=bucket, Key=gzip_key)['Body'].read()
print(len(s))  # check to ensure some data was returned
Run Code Online (Sandbox Code Playgroud)


Har*_*_pb 7

以上答案是针对gzip文件的,对于zip文件,你可以试试

import boto3
import zipfile
from io import BytesIO
bucket = 'bucket1'

s3 = boto3.client('s3', use_ssl=False)
Key_unzip = 'result_files/'

prefix      = "folder_name/"
zipped_keys =  s3.list_objects_v2(Bucket=bucket, Prefix=prefix, Delimiter = "/")
file_list = []
for key in zipped_keys['Contents']:
    file_list.append(key['Key'])
#This will give you list of files in the folder you mentioned as prefix
s3_resource = boto3.resource('s3')
#Now create zip object one by one, this below is for 1st file in file_list
zip_obj = s3_resource.Object(bucket_name=bucket, key=file_list[0])
print (zip_obj)
buffer = BytesIO(zip_obj.get()["Body"].read())

z = zipfile.ZipFile(buffer)
for filename in z.namelist():
    file_info = z.getinfo(filename)
    s3_resource.meta.client.upload_fileobj(
        z.open(filename),
        Bucket=bucket,
        Key='result_files/' + f'{filename}')
Run Code Online (Sandbox Code Playgroud)

这将适用于您的zip文件,您的结果解压缩数据将在result_files文件夹中。确保将内存和时间AWS Lambda增加到最大值,因为某些文件非常大并且需要时间来写入。