You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

S3中Zip文件用ZipEntry获取未压缩大小返回-1的处理问询

解决S3中Zip文件用ZipInputStream获取未压缩大小返回-1的问题

我之前也碰到过一模一样的情况,ZipInputStream的entry.getSize()返回-1,大多是因为它属于流式读取类,要么是还没读到条目元数据里的大小字段,要么是部分不规范的Zip文件没正确存储这个值。下面给你几个实用的解决方案:

方法1:先把S3文件下载到本地临时文件,再用ZipFile处理

ZipFile确实能稳定获取条目未压缩大小,但它需要可随机访问的文件资源,没法直接传入S3路径。你可以先把Zip文件下载到本地临时文件,再用ZipFile解析:

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;

public class S3ZipSizeHandler {
    public static void main(String[] args) throws IOException {
        String bucketName = "你的Bucket名称";
        String zipObjectKey = "存储的Zip文件路径/比如test.zip";
        
        // 创建临时文件,JVM退出时自动删除
        File tempZip = File.createTempFile("s3-temp-zip-", ".zip");
        tempZip.deleteOnExit();
        
        // 从S3下载文件到临时文件
        try (S3Client s3Client = S3Client.create()) {
            GetObjectRequest request = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(zipObjectKey)
                    .build();
            s3Client.getObject(request, ResponseTransformer.toFile(tempZip));
        }
        
        // 用ZipFile解析获取未压缩大小
        try (ZipFile zipFile = new ZipFile(tempZip)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (!entry.isDirectory()) {
                    long uncompressedSize = entry.getSize();
                    System.out.printf("条目%s的未压缩大小:%d字节%n", entry.getName(), uncompressedSize);
                }
            }
        }
    }
}

方法2:用Apache Commons Compress的ZipArchiveInputStream流式处理

如果你不想把整个文件下载到本地,可以用Apache Commons Compress库的ZipArchiveInputStream,它比JDK原生的ZipInputStream更可靠,能准确读取条目元数据:

先添加Maven依赖(如果用Gradle的话对应调整):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.24.0</version> <!-- 建议用最新稳定版 -->
</dependency>

然后是代码示例:

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;

import java.io.IOException;
import java.io.InputStream;

public class S3ZipStreamSizeHandler {
    public static void main(String[] args) throws IOException {
        String bucketName = "你的Bucket名称";
        String zipObjectKey = "存储的Zip文件路径/比如test.zip";
        
        try (S3Client s3Client = S3Client.create()) {
            GetObjectRequest request = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(zipObjectKey)
                    .build();
            // 直接获取S3对象输入流
            try (InputStream s3Stream = s3Client.getObject(request);
                 ZipArchiveInputStream zipStream = new ZipArchiveInputStream(s3Stream)) {
                
                ZipArchiveEntry entry;
                while ((entry = zipStream.getNextZipEntry()) != null) {
                    if (!entry.isDirectory()) {
                        long uncompressedSize = entry.getSize();
                        System.out.printf("条目%s的未压缩大小:%d字节%n", entry.getName(), uncompressedSize);
                    }
                }
            }
        }
    }
}

这个方法不用下载整个文件,直接流式处理,适合大Zip文件的场景。

方法3:手动解析Zip文件头部(进阶场景)

如果既不想依赖第三方库,又不想下载整个文件,可以手动读取Zip文件的末尾部分(中央目录区在Zip文件末尾)解析条目元数据。不过这个需要对Zip文件格式有了解,实现起来比较繁琐,容易出错,只适合对性能要求极高的场景,一般不推荐。

总结一下:优先推荐方法2,兼顾效率和可靠性;如果不能引入第三方库,就用方法1,逻辑简单不易出问题。

内容的提问来源于stack exchange,提问作者praveen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:14:27