通过xftp可以看到目标服务器上面的资源如下:
第一步:导入ftp依赖:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.7</version> <!-- 使用最新版本 -->
</dependency>
首先是通过原生代码来操作:
这里有个坑:如果是匿名登录,账号密码还是要的String username = "anonymous"
即可,密码随意,直接上代码:
下载文件操作:
import com.example.demo.test1.utils.FtpUtil;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class test8 {
public static void main(String[] args) throws Exception {
String server = "ftp.ncbi.nlm.nih.gov";
int port = 21;
String username = "anonymous";
String password = "your_password";
FTPClient ftpClient = new FTPClient();
ftpClient.connect(server, port);
ftpClient.login(username, password);
String remoteFilePath = "/pubmed/updatefiles/pubmed24n1220.xml.gz";
String localFilePath = "D:\\BaiduNetdiskDownload\\pubmed24n1220.xml.gz";
//设置本地被动模式
ftpClient.enterLocalPassiveMode();
ftpClient.setControlEncoding("UTF-8");
// 设置二进制文件类型
//ftpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
try {
// 创建本地文件输出流
OutputStream outputStream = new FileOutputStream(localFilePath);
// 从 FTP 服务器下载文件
boolean success = ftpClient.retrieveFile(remoteFilePath, outputStream);
if (success) {
System.out.println("File downloaded successfully.");
} else {
System.out.println("File download failed.");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 FTP 连接
ftpClient.logout();
ftpClient.disconnect();
}
}
}
这里的远端路径和需要下载的本地路径我都提前把文件名拼上去了,根据需要可以动态拼接:下载结果:
查看文件目录操作:查看/pubmed下的目录:
public class test6 {
public static void main(String[] args) throws Exception{
String server = "ftp.ncbi.nlm.nih.gov";
int port = 21;
String username = "anonymous";
String password = "your_password";
String remoteFilePath2 = "/pubmed";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(username, password);
// 设置本地被动模式
ftpClient.enterLocalPassiveMode();
// 设置二进制文件类型
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 切换到指定文件夹
ftpClient.changeWorkingDirectory(remoteFilePath2);
// 使用listDirectories()获取目录列表
FTPFile[] ftpDirectories = ftpClient.listDirectories();
if (ftpDirectories != null && ftpDirectories.length > 0) {
System.out.println("子目录列表:");
for (FTPFile ftpDirectory : ftpDirectories) {
System.out.println(ftpDirectory.getName());
}
} else {
System.out.println("当前文件夹中没有子目录。");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭 FTP 连接
ftpClient.logout();
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
查看目录下文件操作:查看/pubmed/updatefiles下的gz结尾文件
import com.example.demo.test1.utils.FtpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import java.io.*;
@Slf4j
public class test5 {
public static void main(String[] args) throws Exception {
FTPClient ftpClient = FtpUtil.getFtpClient("ftp.ncbi.nlm.nih.gov", 21, "anonymous", "your_password");
try {
// 切换到指定文件夹
String remoteFolder = "/pubmed/updatefiles";
ftpClient.changeWorkingDirectory(remoteFolder);
// 使用LIST命令获取详细文件列表
String[] fileDetails = ftpClient.listNames();
if (fileDetails != null && fileDetails.length > 0) {
System.out.println("文件列表:");
for (String fileDetail : fileDetails) {
if (fileDetail.endsWith(".gz")) {
System.out.println(fileDetail);
}
}
} else {
System.out.println("文件夹为空或没有权限查看文件列表。");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭 FTP 连接
FtpUtil.disConnect(ftpClient);
}
}
}
这里的登录退出都是使用了FtpUtil工具类,方便很多,直接上工具类代码:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
import java.nio.charset.StandardCharsets;
@Slf4j
public class FtpUtil {
/**
* 获取一个ftp连接
* @param host ip地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @return 返回ftp连接对象
* @throws Exception 连接ftp时发生的各种异常
*/
public static FTPClient getFtpClient(String host, Integer port, String username, String password) throws Exception{
FTPClient ftpClient = new FTPClient();
// 连接服务器
ftpClient.connect(host, port);
int reply = ftpClient.getReplyCode();
if(!FTPReply.isPositiveCompletion(reply)){
log.error("无法连接至ftp服务器, host:{}, port:{}", host, port);
ftpClient.disconnect();
return null;
}
// 登入服务器
boolean login = ftpClient.login(username, password);
if(!login){
log.error("登录失败, 用户名或密码错误");
ftpClient.logout();
ftpClient.disconnect();
return null;
}
// 连接并且成功登陆ftp服务器
log.info("login success ftp server, host:{}, port:{}, user:{}", host, port, username);
// 设置通道字符集, 要与服务端设置一致
ftpClient.setControlEncoding("UTF-8");
// 设置文件传输编码类型, 字节传输:BINARY_FILE_TYPE, 文本传输:ASCII_FILE_TYPE, 建议使用BINARY_FILE_TYPE进行文件传输
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 动模式: enterLocalActiveMode(),被动模式: enterLocalPassiveMode(),一般选择被动模式
ftpClient.enterLocalPassiveMode();
// 切换目录
//ftpClient.changeWorkingDirectory("xxxx");
return ftpClient;
}
/**
* 断开ftp连接
* @param ftpClient ftp连接客户端
*/
public static void disConnect(FTPClient ftpClient){
if(ftpClient == null){
return;
}
try {
log.info("断开ftp连接, host:{}, port:{}", ftpClient.getPassiveHost(), ftpClient.getPassivePort());
ftpClient.logout();
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
log.error("ftp连接断开异常, 请检查");
}
}
/**
* 文件下载
* @param ftpClient ftp连接客户端
* @param path 文件路径
* @param fileName 文件名称
*/
public static void download(FTPClient ftpClient, String path, String fileName) throws Exception {
if(ftpClient == null || path == null || fileName == null){
return;
}
// 中文目录处理存在问题, 转化为ftp能够识别中文的字符集
String remotePath;
try {
remotePath = new String(path.getBytes(StandardCharsets.UTF_8), FTP.DEFAULT_CONTROL_ENCODING);
} catch (UnsupportedEncodingException e) {
remotePath = path;
}
InputStream inputStream = ftpClient.retrieveFileStream(remotePath);
if (inputStream == null) {
log.error("{}在ftp服务器中不存在,请检查", path);
return;
}
FileOutputStream outputStream = new FileOutputStream(fileName);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
try{
byte[] buffer = new byte[2048];
int i;
while ((i = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, i);
bufferedOutputStream.flush();
}
} catch (Exception e) {
log.error("文件下载异常", e);
log.error("{}下载异常,请检查", path);
}
inputStream.close();
outputStream.close();
bufferedInputStream.close();
bufferedOutputStream.close();
// 关闭流之后必须执行,否则下一个文件导致流为空
boolean complete = ftpClient.completePendingCommand();
if(complete){
log.info("文件{}下载完成", remotePath);
}else{
log.error("文件{}下载失败", remotePath);
}
}
/**
* 上传文件
* @param ftpClient ftp连接客户端
* @param sourcePath 源地址
*/
public static void upload(FTPClient ftpClient, String sourcePath) throws Exception{
if(ftpClient == null || sourcePath == null){
return;
}
File file = new File(sourcePath);
if(!file.exists() || !file.isFile()){
return;
}
// 中文目录处理存在问题, 转化为ftp能够识别中文的字符集
String remotePath;
try {
remotePath = new String(file.getName().getBytes(StandardCharsets.UTF_8), FTP.DEFAULT_CONTROL_ENCODING);
} catch (UnsupportedEncodingException e) {
remotePath = file.getName();
}
try(
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = ftpClient.storeFileStream(remotePath);
){
byte[] buffer = new byte[2048];
int length;
while((length = inputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, length);
outputStream.flush();
}
}catch (Exception e){
log.error("文件上传异常", e);
}
// 关闭流之后必须执行,否则下一个文件导致流为空
boolean complete = ftpClient.completePendingCommand();
if(complete){
log.info("文件{}上传完成", remotePath);
}else{
log.error("文件{}上传失败", remotePath);
}
}
}
参考链接:Java从ftp服务器上传与下载文件