gpt4 book ai didi

java - 使用 Java 从 S3 上的文件在 S3 上创建 zip 文件

转载 作者:太空宇宙 更新时间:2023-11-04 09:33:01 26 4
gpt4 key购买 nike

我在 S3 上有很多文件,需要对其进行压缩,然后通过 S3 提供压缩文件。目前,我将它们从流压缩到本地文件,然后再次上传该文件。这会占用大量磁盘空间,因为每个文件大约有 3-10MB,而且我必须压缩多达 100.000 个文件。所以一个 zip 的容量可以超过 1TB。所以我想要一个这样的解决方案:

Create a zip file on S3 from files on S3 using Lambda Node

这里可以看出zip是直接在S3上创建的,不占用本地磁盘空间。但我只是不够聪明,无法将上述解决方案转移到Java中。我还发现有关 java aws sdk 的冲突信息,称他们计划在 2017 年更改流行为。

不确定这是否有帮助,但这就是我到目前为止所做的事情(Upload 是我保存 S3 信息的本地模型)。我刚刚删除了日志记录和其他内容以提高可读性。我认为我不会占用下载空间,将 InputStream 直接“管道”到 zip 中。但就像我说的,我也想避免使用本地 zip 文件并直接在 S3 上创建它。然而,这可能需要使用 S3 作为目标而不是 FileOutputStream 创建 ZipOutputStream。不确定如何做到这一点。

public File zipUploadsToNewTemp(List<Upload> uploads) {
List<String> names = new ArrayList<>();

byte[] buffer = new byte[1024];
File tempZipFile;
try {
tempZipFile = File.createTempFile(UUID.randomUUID().toString(), ".zip");
} catch (Exception e) {
throw new ApiException(e, BaseErrorCode.FILE_ERROR, "Could not create Zip file");
}
try (
FileOutputStream fileOutputStream = new FileOutputStream(tempZipFile);
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {

for (Upload upload : uploads) {
InputStream inputStream = getStreamFromS3(upload);
ZipEntry zipEntry = new ZipEntry(upload.getFileName());
zipOutputStream.putNextEntry(zipEntry);
writeStreamToZip(buffer, zipOutputStream, inputStream);
inputStream.close();
}
zipOutputStream.closeEntry();
zipOutputStream.close();
return tempZipFile;
} catch (IOException e) {
logError(type, e);
if (tempZipFile.exists()) {
FileUtils.delete(tempZipFile);
}
throw new ApiException(e, BaseErrorCode.IO_ERROR,
"Error zipping files: " + e.getMessage());
}
}

// I am not even sure, but I think this takes up memory and not disk space
private InputStream getStreamFromS3(Upload upload) {
try {
String filename = upload.getId() + "." + upload.getFileType();
InputStream inputStream = s3FileService
.getObject(upload.getBucketName(), filename, upload.getPath());
return inputStream;
} catch (ApiException e) {
throw e;
} catch (Exception e) {
logError(type, e);
throw new ApiException(e, BaseErrorCode.UNKOWN_ERROR,
"Unkown Error communicating with S3 for file: " + upload.getFileName());
}
}


private void writeStreamToZip(byte[] buffer, ZipOutputStream zipOutputStream,
InputStream inputStream) {
try {
int len;
while ((len = inputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
} catch (IOException e) {
throw new ApiException(e, BaseErrorCode.IO_ERROR, "Could not write stream to zip");
}
}

最后是上传源代码。输入流是从临时 Zip 文件创建的。

public PutObjectResult upload(InputStream inputStream, String bucketName, String filename, String folder) {
String uploadKey = StringUtils.isEmpty(folder) ? "" : (folder + "/");
uploadKey += filename;

ObjectMetadata metaData = new ObjectMetadata();

byte[] bytes;
try {
bytes = IOUtils.toByteArray(inputStream);
} catch (IOException e) {
throw new ApiException(e, BaseErrorCode.IO_ERROR, e.getMessage());
}
metaData.setContentLength(bytes.length);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

PutObjectRequest putObjectRequest = new PutObjectRequest(bucketPrefix + bucketName, uploadKey, byteArrayInputStream, metaData);
putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);

try {
return getS3Client().putObject(putObjectRequest);
} catch (SdkClientException se) {
throw s3Exception(se);
} finally {
IOUtils.closeQuietly(inputStream);
}
}

刚刚发现一个与我需要的类似的问题也没有答案:

Upload ZipOutputStream to S3 without saving zip file (large) temporary to disk using AWS S3 Java

最佳答案

您可以从 S3 数据获取输入流,然后压缩这批字节并将其流回 S3

        long numBytes;  // length of data to send in bytes..somehow you know it before processing the entire stream
PipedOutputStream os = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(os);
ObjectMetadata meta = new ObjectMetadata();
meta.setContentLength(numBytes);

new Thread(() -> {
/* Write to os here; make sure to close it when you're done */
try (ZipOutputStream zipOutputStream = new ZipOutputStream(os)) {
ZipEntry zipEntry = new ZipEntry("myKey");
zipOutputStream.putNextEntry(zipEntry);

S3ObjectInputStream objectContent = amazonS3Client.getObject("myBucket", "myKey").getObjectContent();
byte[] bytes = new byte[1024];
int length;
while ((length = objectContent.read(bytes)) >= 0) {
zipOutputStream.write(bytes, 0, length);
}
objectContent.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
amazonS3Client.putObject("myBucket", "myKey", is, meta);
is.close(); // always close your streams

关于java - 使用 Java 从 S3 上的文件在 S3 上创建 zip 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56846856/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com