FTP下载的文件处理报错:java.io.IOException: central directory is empty, can't expand corrupt archive.

一、问题来源

  最近做一个海安项目,不同网域之间数据需要通过FTP摆渡文件的形式同步,因此代码就涉及到FTP文件压缩上传、下载解压的操作。windows本地开发环境对文件下载解压没有问题,发布linux个别文件报如下错误:

org.apache.tools.ant.BuildException: Error while expanding /opt/opsmgr/web/components/tomcat85linux64.2/webapps/ctm01favorite/WEB-INF/classes/download/1648798558_zap.zip java.io.IOException: central directory is empty, can't expand corrupt archive.         at org.apache.tools.ant.taskdefs.Expand.expandFile(Expand.java:206)         at org.apache.tools.ant.taskdefs.Expand.execute(Expand.java:148)         at com.hikvision.js.ctm01favorite.utils.CompressUtils.decompressionZip(CompressUtils.java:46)         at com.hikvision.js.ctm01favorite.task.ScheduledTasks.handleZipFile(ScheduledTasks.java:123)         at com.hikvision.js.ctm01favorite.task.ScheduledTasks.lambda$ftpDataReceive$1(ScheduledTasks.java:83)         at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:67)         at com.hikvision.starfish.log.business.async.BusLogRunnable.run(BusLogRunnable.java:33)         at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)         at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)         at java.base/java.lang.Thread.run(Thread.java:834) Caused by: java.io.IOException: central directory is empty, can't expand corrupt archive.         at org.apache.tools.zip.ZipFile.populateFromCentralDirectory(ZipFile.java:459)         at org.apache.tools.zip.ZipFile.<init>(ZipFile.java:215)         at org.apache.tools.ant.taskdefs.Expand.expandFile(Expand.java:184)         ... 9 common frames omitted

排查发现报错的就是固定的那几个文件,本地windows环境检查发现文件状态正常,没有损坏的情况。

二、解决方法

  FTP文件下载时设置以字节的方式进行传输,ftpClient.setFileType(FTP.BINARY_FILE_TYPE);完整代码如下:

public boolean downloadFileNew(String pathname, String filename, String localpath, FTPClient ftpClient) {         boolean flag = false;         OutputStream os = null;         try {             logger.info(开始下载文件);             // 切换FTP目录             boolean changeFlag = ftpClient.changeWorkingDirectory(pathname);             logger.info(changeFlag== + changeFlag);              ftpClient.setFileType(FTP.BINARY_FILE_TYPE);             ftpClient.enterLocalPassiveMode();             ftpClient.setRemoteVerificationEnabled(false);             // 查看有哪些文件夹 以确定切换的ftp路径正确             String[] a = ftpClient.listNames();             logger.info(a[0]);              FTPFile[] ftpFiles = ftpClient.listFiles();             for (FTPFile file : ftpFiles) {                 if (filename.equalsIgnoreCase(file.getName())) {                     File localFile = new File(localpath + / + file.getName());                     os = new FileOutputStream(localFile);                     ftpClient.retrieveFile(file.getName(), os);                     os.close();                 }             }             //ftpClient.logout();             flag = true;             logger.info(下载文件成功);         } catch (Exception e) {             logger.error(下载文件失败, e);         } finally {             if (null != os) {                 try {                     os.close();                 } catch (IOException e) {                     e.printStackTrace();                 }             }         }         return flag;     }

问题解决。

三、总结

  部分文件上传时采用的方式是二进制方式,那么下载如果不采用二进制方式下载可能会出现问题。因此FTP文件操作尽量文件类型都设置成二进制类型。