使用Apache Commons Net向FTP传输文件后体积增大问题排查
问题分析与解决方案
核心问题:错误的FTPClient方法调用
你遇到的文件体积变大问题,根源一眼就能看出来——你把FTPClient设置文件类型的方法用错了!看这段代码:
ftpClient.setFileTransferMode(FTP.BINARY_FILE_TYPE);
这里犯了个关键混淆:setFileTransferMode()是用来配置FTP的传输模式(比如流模式、块模式)的,而设置文件传输的类型(二进制/ASCII)应该用setFileType()方法!
当你错误地用setFileTransferMode传入FTP.BINARY_FILE_TYPE时,FTPClient并没有真正切换到二进制传输模式,默认还是用ASCII模式处理文件。对于你这种500MB的二进制文件,ASCII模式会自动转换某些字节(比如换行符相关的字节),直接导致文件体积膨胀,甚至可能损坏文件内容。
修正方案
把那行错误的代码替换成正确的文件类型设置:
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
同时保留enterLocalPassiveMode()的设置(这个是正确的,用于被动模式连接,避免防火墙问题)。
修正后的完整核心代码
JSch jsch = new JSch(); Session session = jsch.getSession("username", "sftp.server.address", 22); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword("password"); session.connect(); //connect to sftp Channel channel = session.openChannel("sftp"); channel.connect(); ChannelSftp sftpChannel = (ChannelSftp) channel; //connect to ftp FTPClient ftpClient = new FTPClient(); ftpClient.connect("ftp.server.address", 21); ftpClient.login("username", "password"); ftpClient.enterLocalPassiveMode(); // 修正:正确设置二进制文件传输类型 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); //getting file as an inputstream from the sftp InputStream sftpFileInputStream = sftpChannel.get("/temp/file1"); //sending sftp fileinputstream directry to the ftp server ftpClient.storeFile("file1", sftpFileInputStream); // 补充:关闭输入流,避免资源泄漏 sftpFileInputStream.close(); ftpClient.disconnect(); sftpChannel.exit(); session.disconnect();
另外提醒下:你之前的代码没有关闭从SFTP获取的InputStream,建议加上关闭操作,防止资源浪费。
为什么URLConnection方式没问题?
因为URLConnection处理FTP请求时,默认会采用二进制模式传输(或者说它不会像FTPClient那样把传输模式和文件类型的设置混淆),所以没有触发字节转换的问题,文件体积自然正常。
验证建议
传输完成后,你可以对比源文件和目标文件的哈希值(比如MD5、SHA-256),确认文件内容没有损坏。
内容的提问来源于stack exchange,提问作者Nikolay Hristov
相关产品推荐
相关产品推荐

