Avi*_*vis 4 java amazon-s3 amazon-web-services aws-lambda
我有一个名为“Source”的 S3 存储桶。许多“.tgz”文件被实时推送到该存储桶中。我编写了一个 Java 代码来提取“.tgz”文件并将其推送到“目的地”存储桶中。我将代码推送为 Lambda 函数。我在我的 Java 代码中得到了“.tgz”文件作为 InputStream。如何在 Lambda 中提取它?我无法在 Lambda 中创建文件,它在 JAVA 中抛出“FileNotFound(Permission Denied)”。
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
Run Code Online (Sandbox Code Playgroud)
由于其中一个响应是在 Python 中,我提供了这种语言的替代解决方案。
使用/tmp文件系统的解决方案的问题是,AWS 只允许在那里存储512 MB(阅读更多)。为了解压或解压较大的文件,最好使用io包和BytesIO类并纯粹在内存中处理文件内容。AWS 允许为 Lambda 分配最多 3GB 的 RAM,这显着扩展了最大文件大小。我成功地测试了 1GB S3 文件的解压。
在我的情况下,将大约 2000 个文件从 1GB tar 文件解压到另一个 S3 存储桶需要 140 秒。它可以通过利用多个线程将未压缩的文件上传到目标 S3 存储桶来进一步优化。
下面的示例代码展示了单线程解决方案:
import boto3
import botocore
import tarfile
from io import BytesIO
s3_client = boto3.client('s3')
def untar_s3_file(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
input_tar_file = s3_client.get_object(Bucket = bucket, Key = key)
input_tar_content = input_tar_file['Body'].read()
with tarfile.open(fileobj = BytesIO(input_tar_content)) as tar:
for tar_resource in tar:
if (tar_resource.isfile()):
inner_file_bytes = tar.extractfile(tar_resource).read()
s3_client.upload_fileobj(BytesIO(inner_file_bytes), Bucket = bucket, Key = tar_resource.name)
Run Code Online (Sandbox Code Playgroud)
不要使用Fileor 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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8287 次 |
| 最近记录: |