Apache Commons Net下载FTP PDF文件损坏,设二进制模式仍无解求助
解决Apache Commons Net FTP传输PDF文件损坏的问题
我之前也碰到过类似的PDF传输损坏的坑——明明文件大小差不离,但打开就是报错,设置了二进制模式也没用,折腾了好一阵才找到几个关键排查点,给你参考:
1. 先去掉压缩传输模式试试
你代码里用了FTP.COMPRESSED_TRANSFER_MODE,这个模式依赖FTP服务器支持压缩协议,很多服务器默认是不开启的。而且PDF本身已经是压缩格式,强行开FTP压缩反而可能导致数据在编码/解码过程中变形。
建议直接注释掉这行,改用默认的流传输模式:
// 删掉这行:ftpClient.setFileTransferMode(FTP.COMPRESSED_TRANSFER_MODE); ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE); // 显式设置流模式,和默认一致但更稳妥
2. 调整设置顺序,确保二进制模式生效
有时候设置方法的调用顺序会影响最终效果,建议先设置文件类型,再设置传输模式,避免类型被覆盖:
ftpClient.connect(host, port); ftpClient.enterLocalPassiveMode(); // 先设置二进制类型 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // 再设置传输模式 ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
还可以加个日志确认当前类型是否生效:
// 二进制类型在FTP协议里标识为"I",ASCII是"A" System.out.println("当前文件传输类型:" + ftpClient.getType());
3. 关键:调用completePendingCommand()收尾传输
这是很多人容易忽略的点!FTP传输完成后,必须调用completePendingCommand()等待服务器确认传输结束,否则可能会有末尾数据截断的情况——看起来文件大小差不多,但内容已经损坏。
完善你的finally块:
finally { // 先关闭输出流 if (outputStream != null) { try { outputStream.flush(); // 确保缓冲区数据全部写入 outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } // 关键:等待服务器确认传输完成 if (ftpClient.isConnected()) { try { if (!ftpClient.completePendingCommand()) { System.err.println("FTP服务器未确认传输完成,可能存在数据损坏"); resultOk = false; } ftpClient.disconnect(); } catch (IOException e) { e.printStackTrace(); } } }
4. 用工具验证服务器端文件和本地文件的差异
找个二进制对比工具(比如Beyond Compare)对比服务器上的原始PDF和你下载的文件:
- 如果是某些字节被替换(比如换行符
\n变成\r\n),说明二进制模式确实没生效,回头检查代码里的设置逻辑; - 如果是末尾少了几个字节,大概率是没调用
completePendingCommand()导致的截断; - 如果差异是随机的,可能是网络不稳定,可以试试增加重试逻辑。
5. 用命令行FTP工具做对照测试
用系统自带的ftp命令或者FileZilla手动传输同一个PDF文件,如果手动传输后文件正常,那问题肯定在代码里;如果手动传输也损坏,那要联系FTP服务器管理员检查服务器配置(比如是否强制ASCII模式)。
内容的提问来源于stack exchange,提问作者Timo Bruntjn
相关产品推荐
相关产品推荐

