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文件操作尽量文件类型都设置成二进制类型。