如何使用Java AWS SDK在S3存储桶内压缩指定目录对象
在S3中压缩Demo/目录下对象的Java实现方案
Amazon S3没有原生API支持直接在桶内对已有对象进行压缩操作,你需要通过下载对象→本地压缩→上传压缩包的流程来实现,以下是基于AWS Java SDK v2的具体实现步骤:
1. 引入依赖
确保项目中包含AWS S3 SDK的依赖,Maven配置示例:
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.25.0</version> <!-- 使用最新稳定版本 --> </dependency>
2. 完整代码实现
import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Object; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class S3DirectoryCompressor { // 替换为你的存储桶名称 private static final String BUCKET_NAME = "your-bucket-name"; // 要压缩的目标前缀 private static final String TARGET_PREFIX = "Demo/"; // 压缩包在S3中的存储路径 private static final String ZIP_OBJECT_KEY = "Demo/demo_all_files.zip"; public static void main(String[] args) { // 初始化S3客户端(默认会读取本地AWS配置,或可自定义配置) try (S3Client s3Client = S3Client.create()) { // 1. 列出Demo/下的所有对象键 List<String> objectKeys = listAllObjectsUnderPrefix(s3Client, BUCKET_NAME, TARGET_PREFIX); // 2. 下载对象并生成本地临时ZIP文件 File tempZipFile = generateZipFromS3Objects(s3Client, BUCKET_NAME, objectKeys); // 3. 将ZIP文件上传回S3 uploadZipToS3(s3Client, BUCKET_NAME, ZIP_OBJECT_KEY, tempZipFile); // 清理临时文件 if (!tempZipFile.delete()) { System.err.println("警告:临时压缩文件删除失败,请手动清理"); } System.out.println("压缩完成,压缩包已保存至S3:" + ZIP_OBJECT_KEY); } catch (Exception e) { e.printStackTrace(); } } // 列出指定前缀下的所有对象键 private static List<String> listAllObjectsUnderPrefix(S3Client s3Client, String bucketName, String prefix) { List<String> objectKeys = new ArrayList<>(); ListObjectsV2Request request = ListObjectsV2Request.builder() .bucket(bucketName) .prefix(prefix) .build(); ListObjectsV2Response response; do { response = s3Client.listObjectsV2(request); for (S3Object obj : response.contents()) { objectKeys.add(obj.key()); } // 处理分页,获取下一批对象 request = request.toBuilder().continuationToken(response.nextContinuationToken()).build(); } while (response.isTruncated()); return objectKeys; } // 下载S3对象并打包成ZIP private static File generateZipFromS3Objects(S3Client s3Client, String bucketName, List<String> objectKeys) throws IOException { // 创建临时文件存储ZIP内容 File tempZip = File.createTempFile("s3-demo-zip-", ".zip"); try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tempZip))) { for (String key : objectKeys) { // 从S3获取对象输入流 try (InputStream objInputStream = s3Client.getObject(b -> b.bucket(bucketName).key(key))) { // 设置ZIP内的文件名称(去掉前缀,避免压缩包内嵌套Demo目录) String entryName = key.substring(TARGET_PREFIX.length()); ZipEntry entry = new ZipEntry(entryName); zipOut.putNextEntry(entry); // 读取S3对象内容并写入ZIP byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = objInputStream.read(buffer)) != -1) { zipOut.write(buffer, 0, bytesRead); } zipOut.closeEntry(); } } } return tempZip; } // 将ZIP文件上传至S3 private static void uploadZipToS3(S3Client s3Client, String bucketName, String zipKey, File zipFile) throws IOException { PutObjectRequest putRequest = PutObjectRequest.builder() .bucket(bucketName) .key(zipKey) .build(); s3Client.putObject(putRequest, zipFile.toPath()); } }
3. 关键注意事项
- 权限配置:确保你的S3客户端拥有
s3:ListBucket(列出对象)、s3:GetObject(下载对象)、s3:PutObject(上传压缩包)的权限。 - 资源占用:如果文件总体积较大,建议监控磁盘空间;也可以改用内存流,但大文件场景下磁盘临时文件更稳定。
- 分页处理:代码中已经处理了S3列表的分页逻辑,即使对象数量超过1000个也能完整获取。
- 替代方案:如果不想在本地处理,可以编写Java Lambda函数,在云端完成下载、压缩、上传流程,避免占用本地资源,但需要配置Lambda的S3权限和触发条件。
内容的提问来源于stack exchange,提问作者vyas
相关产品推荐
相关产品推荐

