本文FTP连接的相关操作均在 被动模式 下进行。
FTP的端口分两种:控制端口和 数据端口 。
连接FTP服务器时的port的默认21为控制端口。
FTP的数据端口顾名思义就是用来进行数据操作的端口。其又分为两种模式:主动模式与 被动模式 。
主动模式端口默认为20,被动模式端口为范围3000/4000。
当服务器上存在防火墙时,需注意开放相关端口的问题。
关于断点续传,可以在开始新的下载时对比本地与远程服务器上文件大小,当本地小于远程的时候,通过如下设置使其接着之前的进度继续下载:
ftpClient.setRestartOffset(localFile.length());完整示例代码请见最后相关下载部分。
相关依赖
完整示例使用gradle构建,基于springboot2.1.8,所用FTP相关的依赖如下:
implementation "commons-net:commons-net:3.6" implementation "commons-io:commons-io:2.6"连接服务器并登录
public FTPClient connect(String hostname, Integer port, String username, String password) throws IOException { // 创建连接 FTPClient ftpClient = new FTPClient(); ftpClient.connect(hostname, port); // 设置用于FTP控制连接的编码:UTF-8等 ftpClient.setControlEncoding(properties.getEncoding()); log.error("windcoder.com:connect=>\t"+ftpClient.getReplyString()); // 登录服务器 ftpClient.login(username, password); log.error("login=>\t"+ftpClient.getReplyString()); return ftpClient; }退出并断开连接
public void disconnect(FTPClient ftpClient) throws IOException { ftpClient.logout(); log.error("disLogin=>\t"+ftpClient.getReplyString()); ftpClient.disconnect(); log.error("disConnect=>\t"+ftpClient.getReplyString()); }获取并下载文件关键代码
// 进入文件所在远程目录ftpClient.changeWorkingDirectory(remoteFilePath);// 开启被动模式ftpClient.enterLocalPassiveMode();// 设置以二进制方式传输ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);// 获取文件,listFiles参数为空时获取当前目录下所有文件,包含文件名时,可通过files.length == 1判断是否存在该文件FTPFile[] files = ftpClient.listFiles(tmpFileName);// 获取文件大小long remoteSize = files[0].getSize();// 返回一个用于读取服务器上名为tmpFileName的文件的InputStream,InputStream in = ftpClient.retrieveFileStream(tmpFileName);// 创建一个用于写入localFile文件的输出流,若需追加写,则添加并将第二个参数设为true。FileOutputStream out = new FileOutputStream(localFile, true);// 将in复制到out,具体方式可自由实现,这里展示IOUtils方式if (remoteSize - localSize >= 2 * FileUtils.ONE_GB) { // 文件大小超过2G时 IOUtils.copyLarge(in, out);}else { IOUtils.copy(in, out);}// 刷新此输出流,并强制写出所有缓冲的输出字节。 flush的一般约定是,调用它表明,如果先前写入的任何字节已由输出流的实现缓冲,则应立即将这些字节写入其预期的目标。out.flush();// 关闭相关流,这里展示IOUtils方式IOUtils.closeQuietly(in);IOUtils.closeQuietly(out);// 接收来自服务器的完成答复并验证整个事务是否成功/** * 有些FTPClient方法不能完成整个FTP命令序列来完成事务。 这些命令要求程序员在收到肯定的中间命令后采取一些措施。 * 程序员的代码完成其操作后,必须调用此方法以接收来自服务器的完成答复并验证整个事务是否成功。 * */ftpClient.completePendingCommand();获取并上传文件关键代码
// 创建输入流FileInputStream fis = new FileInputStream(filePath);// 进入文件所在FTP远程目录ftpClient.changeWorkingDirectory(uploadPath);// 开启被动模式ftpClient.enterLocalPassiveMode();// 调整ftp传输模式为二进制方式ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);// 调用ftp的方法上载// 从给定InputStream中获取输入并以给定文件名fileName将文件保存在FTP服务器上。boolean ret = ftpClient.storeFile(fileName, fis);// 关闭文件流fis.close();
评论