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

Windows本地正常服务器部署报错:ZipException invalid distance too far back

问题:FTP获取Zip文件解析失败,报java.util.zip.ZipException: invalid distance too far back

本地Windows环境运行正常,部署到服务器后抛出该错误,相关代码及报错信息如下:

业务代码

wrapper.connect();
byte[] archiveBytes = wrapper.retrieveFileBytes("some path");
try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(archiveBytes))) {
    ZipEntry entry;
    while ((entry = zis.getNextEntry()) != null) {
        byte[] fileBytes = FileUtils.readZipEntry(zis);
        if (fileBytes.length == 0) {
            continue;
        }
        try (InputStream inputStream = new ByteArrayInputStream(fileBytes)) {
            var model = ftpFileReader.read(inputStream);
            domains.add(model);
        }
    }
}
return domains;

工具方法

public static byte[] readZipEntry(ZipInputStream zis) throws IOException {
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
        byte[] buffer = new byte[1024];
        int count;
        while ((count = zis.read(buffer)) > -1) {
            outputStream.write(buffer, 0, count);
        }
        return outputStream.toByteArray();
    } finally {
        zis.closeEntry();
    }
}

报错信息

java.util.zip.ZipException: invalid distance too far back

完整堆栈信息

org.springframework.retry.RetryException: Non-skippable exception in recoverer while processing; nested exception is java.util.zip.ZipException: invalid distance too far back
        at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$2.recover(FaultTolerantChunkProcessor.java:299) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:539) ~[spring-retry-1.3.3.jar!/:na]
        at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:387) ~[spring-retry-1.3.3.jar!/:na]
        at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:255) ~[spring-retry-1.3.3.jar!/:na]
        at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:217) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.transform(FaultTolerantChunkProcessor.java:308) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:210) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.23.jar!/:5.3.23]
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:139) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149) ~[spring-batch-core-4.3.7.jar!/:4.3.7]
        at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: java.util.zip.ZipException: invalid distance too far back
        at java.base/java.util.zip.InflaterInputStream.read(Unknown Source) ~[na:na]
        at java.base/java.util.zip.ZipInputStream.read(Unknown Source) ~[na:na]
        at java.base/java.util.zip.ZipInputStream.closeEntry(Unknown Source) ~[na:na]
        at ftp.utils.FileUtils.readZipEntry(FileUtils.java:18)

排查思路与解决方案

错误本质

该错误是Zip文件损坏导致的解压失败,本地正常但服务器异常,核心原因是FTP传输模式不匹配:Windows默认用ASCII模式传输,若服务器仍用ASCII模式传输二进制Zip文件,会篡改字节(比如转换换行符、截断特殊字节),最终破坏Zip文件结构。

解决方案

  1. 强制FTP使用二进制模式传输
    在获取文件前设置传输模式为二进制,以Apache Commons Net的FTPClient为例:

    wrapper.connect();
    // 新增:设置二进制传输模式,避免字节篡改
    wrapper.setFileType(FTP.BINARY_FILE_TYPE);
    byte[] archiveBytes = wrapper.retrieveFileBytes("some path");
    
  2. 验证文件完整性

    • 在服务器上把下载的archiveBytes保存为本地文件,用unzip命令尝试解压,确认是否损坏;
    • 对比本地和服务器下载文件的MD5值,不一致则说明传输过程中字节被篡改。
  3. 修正工具方法的异常处理
    当前readZipEntry的finally块调用closeEntry()时,若之前读取流已抛出异常,closeEntry()会继续读取流导致二次错误,建议增加异常捕获:

    public static byte[] readZipEntry(ZipInputStream zis) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[4096]; // 增大缓冲区提升效率
            int count;
            while ((count = zis.read(buffer)) != -1) {
                outputStream.write(buffer, 0, count);
            }
            return outputStream.toByteArray();
        } finally {
            try {
                zis.closeEntry();
            } catch (IOException e) {
                // 记录日志,避免closeEntry的异常覆盖原读取异常
                e.printStackTrace();
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:24:59