使用Apache FTPClient下载PNG仅服务器1出现损坏的问题求助
问题根源与修复方案
嘿,这个问题我之前处理过好几次!核心问题出在FTP传输模式的选择上——你的代码没有显式指定二进制传输模式,而Apache Commons Net的FTPClient默认使用的是ASCII模式,这对PNG这类二进制文件来说完全不适用。
为什么只有服务器1出问题?
ASCII模式是为文本文件设计的,它会自动转换换行符(比如把Unix的LF转换成Windows的CRLF)。PNG文件的二进制数据里可能包含了被ASCII模式误判为换行符的字节序列,服务器1的FTP服务严格执行了ASCII模式的转换规则,导致额外插入了字节(你看到的4706比4686多了20字节,大概率是多处换行符转换导致的)。
而服务器2、3可能因为FTP配置、文件存储格式的原因,ASCII模式下没有触发换行符转换;至于Total Commander,它会自动识别.png后缀属于二进制文件,默认用二进制模式下载,所以能拿到正确的文件。
修复代码
只需要在登录FTP服务器后,显式设置文件传输类型为二进制即可,修改后的代码片段如下:
FTPClient ftpClient = new FTPClient(); ftpClient.connect("...", PORT); ftpClient.login("...", "..."); // 关键:设置二进制传输模式,必须在登录后、开始传输前调用 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); FTPFile[] imageFiles = ftpClient.listFiles(distantPathForImages); for (FTPFile imageFile : imageFiles) { InputStream inputStream = ftpClient.retrieveFileStream(distantPathForImages + imageFile.getName()); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(new File(PATHDESTCSS + imageFile.getName()))); byte[] bytesArray = new byte[65536]; int bytesRead; while ((bytesRead = inputStream.read(bytesArray)) != -1) { outputStream.write(bytesArray, 0, bytesRead); } outputStream.close(); inputStream.close(); ftpClient.completePendingCommand(); }
额外建议
- 对于所有非文本文件(图片、压缩包、视频等),都必须使用二进制传输模式,避免数据损坏。
- 如果你需要同时传输文本和二进制文件,记得在切换文件类型时重新调用
setFileType方法。
内容的提问来源于stack exchange,提问作者Jordan Noel
相关产品推荐
相关产品推荐

