AWS Lambda:如何提取S3存储桶中的tgz文件并将其放入另一个S3存储桶中
问题描述:
我有一个名为“Source”的S3存储桶。许多'.tgz'文件正在被实时推入该存储区。我编写了一个用于提取'.tgz'文件并将其推入“目标”存储区的Java代码。我将我的代码推送为Lambda函数。我在我的Java代码中将'.tgz'文件作为InputStream。如何在Lambda中提取它?我无法在Lambda中创建文件,它会在JAVA中引发“FileNotFound(Permission Denied)”。AWS Lambda:如何提取S3存储桶中的tgz文件并将其放入另一个S3存储桶中
AmazonS3 s3Client = new AmazonS3Client();
S3Object s3Object = s3Client.getObject(new GetObjectRequest(srcBucket, srcKey));
InputStream objectData = s3Object.getObjectContent();
File file = new File(s3Object.getKey());
OutputStream writer = new BufferedOutputStream(new FileOutputStream(file)); <--- It throws FileNotFound(Permission denied) here
答
不要使用File
或FileOutputStream
,使用s3Client.putObject()
。要阅读tgz文件,您可以使用Apache Commons Compress。例如:
ArchiveInputStream tar = new ArchiveInputStreamFactory().
createArchiveInputStream("tar", new GZIPInputStream(objectData));
ArchiveEntry entry;
while ((entry = tar.getNextEntry()) != null) {
if (!entry.isDirectory()) {
byte[] objectBytes = new byte[entry.getSize()];
tar.read(objectBytes);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(objectBytes.length);
metadata.setContentType("application/octet-stream");
s3Client.putObject(destBucket, entry.getName(),
new ByteArrayInputStream(objectBytes), metadata);
}
}
答
import boto3
import botocore
import tarfile
from tarfile import TarInfo
from botocore.client import Config
s3_client = boto3.client('s3')
s3_resource=boto3.resource('s3')
def lambda_handler(event, context):
bucket =event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
new_bucket='uncompressed-data' #new bucket name
new_key=key[:-4]
try:
s3_client.download_file(bucket, key, '/tmp/file')
if(tarfile.is_tarfile('/tmp/file')):
tar = tarfile.open('/tmp/file', "r:gz")
for TarInfo in tar:
tar.extract(TarInfo.name, path='/tmp/extract/')
s3_client.upload_file('/tmp/extract/'+TarInfo.name,new_bucket, new_key)
tar.close()
except Exception as e:
print(e)
raise e
使用Python 3.6和触发obejctcreated(全部),后缀名为 “.tgz” 的事件。希望这可以帮助你。看看这个Link
你的建议是写回到目标桶。但我的问题是如何在lambda函数中提取tgz? – Avis
AWS或lambda提取'tgz'没有什么特别之处。我已经使用标准Java库和Apache Commons Compress更新了我的答案。 – ataylor
这将导致文件末尾出现空值,顺便说一句。 tar.read(objectBytes)将读取缓冲区中的任何内容,但不能保证读取整个文件,因此objectBytes最后会留下一堆空值。 – Fluffycloud