上传文件到FTP服务器,工具类
一、工具类
package com.zyf.study_fileupload.controller;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
import java.util.TimeZone;
import java.util.logging.Logger;
public class FtpUtil {
private FTPClient ftpClient;
private String strIp; // 服务器IP地址
private int intPort; // FTP服务器端口号
private String username; // 用户名
private String password; // 密码
private static Logger logger = Logger.getLogger(FtpUtil.class.getName());
// FtpClient的Set和Get函数
public FTPClient getFtpClient() {
return ftpClient;
}
public void setFtpClient(FTPClient ftpClient) {
this.ftpClient = ftpClient;
}
/**
* Ftp构造函数
* 用于创建FTPClient对象,并封装连接FTP所需信息
*/
public FtpUtil(String strIp, int intPort, String username, String password) {
this.strIp = strIp;
this.intPort = intPort;
this.username = username;
this.password = password;
this.ftpClient = new FTPClient();
}
/**
* 与FTP服务器建立连接
*/
public boolean ftpConnect() throws IOException {
boolean isLogin = false;
FTPClientConfig ftpClientConfig = new FTPClientConfig();
ftpClientConfig.setServerTimeZoneId(TimeZone.getDefault().getID());
this.ftpClient.setControlEncoding("utf-8");
this.ftpClient.enterLocalPassiveMode();
this.ftpClient.configure(ftpClientConfig);
try {
if (this.intPort > 0) {
this.ftpClient.connect(this.strIp,this.intPort);
} else {
this.ftpClient.connect(this.strIp);
}
// FTP服务器连接回答
int reply = this.ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
this.ftpClient.disconnect();
logger.info("登录FTP服务失败");
return false;
}
if (!ftpClient.login(this.username,this.password)) {
this.ftpClient.disconnect();
logger.info("登陆失败,用户名或密码错误!");
return false;
}
// 设置传输协议
this.ftpClient.enterLocalPassiveMode();
this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
logger.info("恭喜"+this.username+"成功登陆FTP服务器");
isLogin = true;
} catch (Exception e) {
e.printStackTrace();
logger.info(this.username+"登录FTP服务失败"+e.getMessage());
}
this.ftpClient.setBufferSize(1024*2);
this.ftpClient.setDataTimeout(30 * 1000);
return isLogin;
}
/**
* 关闭FTP服务器连接
*/
public void ftpDisConnect() {
if (null != this.ftpClient && this.ftpClient.isConnected()) {
try {
boolean result = this.ftpClient.logout(); // 退出FTP服务器
if (result) {
logger.info("成功退出服务器");
}
} catch (IOException e) {
e.printStackTrace();
logger.warning("退出FTP服务器异常"+e.getMessage());
} finally {
try {
this.ftpClient.disconnect(); // 关闭FTP服务器的连接
} catch (IOException e) {
e.printStackTrace();
logger.warning("关闭FTP服务器异常!!");
}
}
}
}
/**
* 上传文件到FTP服务器
* @param localFile 本地文件(前端发送)
* @param romotUpLoadPath 上传服务器路径(为空则为FTP服务器根目录)
* @return boolean (当返回值为true时,将文件上传路径、文件名存入数据库)
*/
public boolean uploadFile(File localFile,String romotUpLoadPath) {
BufferedInputStream inStream = null;
try {
this.ftpClient.changeWorkingDirectory(romotUpLoadPath); // 改变工作路径(为空则为切换为FTP服务器根路径)
inStream = new BufferedInputStream(new FileInputStream(localFile)); // 将本地(传入)文件转化为输入流
logger.info(localFile.getName()+"开始上传...");
boolean success = this.ftpClient.storeFile(localFile.getName(),inStream); // 上传文件(记得开放端口)返回true/false
if (success) {
logger.info(localFile.getName()+"上传成功");
return true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
logger.info(localFile+"未找到");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 下载文件
* @param remoteFileName 待下载文件名称(通过数据库字段或存放路径获取)
* @param localDires 下载到本地的路径(前端选择下载路径)
* @param remoteDownLoadPath remoteFileName所在的路径(通过数据库存放路径获取)
* @return
*/
public boolean downloadFile(String remoteFileName,String localDires,String remoteDownLoadPath) {
String strFilePath = localDires + "\\" + remoteFileName;
BufferedOutputStream outStream = null;
boolean success = false;
try {
this.ftpClient.changeWorkingDirectory(remoteDownLoadPath); // changeWorkingDirectory()路径切换方法
outStream = new BufferedOutputStream(new FileOutputStream(strFilePath)); // 将文件转化为输出流
logger.info(remoteFileName+"开始下载...");
success = this.ftpClient.retrieveFile(remoteFileName,outStream);
if (success == true) {
logger.info(remoteFileName + "成功下载到" + strFilePath);
return success;
}
} catch (Exception e) {
e.printStackTrace();
logger.info(remoteFileName+"下载失败");
} finally {
if (null != outStream) {
try {
outStream.flush();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (success == false) {
logger.info(remoteFileName+"下载失败!!!");
}
return success;
}
/**
* 上传文件夹(文件夹名称不能相同)
* @param localDirectory 本地文件夹
* @param remoteDirectoryPath FTP服务器路径
* @return
*/
public boolean uploadDirectory(String localDirectory,String remoteDirectoryPath) {
File src = new File(localDirectory);
try {
remoteDirectoryPath = remoteDirectoryPath + "/" + src.getName();
boolean bool = this.ftpClient.makeDirectory(remoteDirectoryPath); // 创建目录
if (!bool) {
logger.info("创建"+remoteDirectoryPath+"目录失败");
return false;
}
} catch (IOException e) {
e.printStackTrace();
logger.info(remoteDirectoryPath+"目录创建失败");
}
// 创建成功,扫描文件夹中的文件
File[] allFile = src.listFiles(); // 创建文件数组
for (int currentFile = 0;currentFile < allFile.length;currentFile++) {
if (!allFile[currentFile].isDirectory()) { // 判断当前元素不是文件夹
String srcName = allFile[currentFile].getPath();
uploadFile(new File(srcName),remoteDirectoryPath); // 调用上传文件方法,将文件夹中的文件上传
}
}
for (int currentFile = 0;currentFile < allFile.length;currentFile++) {
if (allFile[currentFile].isDirectory()) { // 判断当前元素是文件夹
// 递归,调用上传文件夹方法(实现多级文件夹上传)
uploadDirectory(allFile[currentFile].getPath(),remoteDirectoryPath);
}
}
return true;
}
/**
* 下载文件夹
* @param localDirectoryPath
* @param remoteDirectory 远程文件夹
* @return
*/
private String strFileName = "/";
public boolean downLoadDirectory(String localDirectoryPath,String remoteDirectory) {
try {
String fileName = new File(remoteDirectory).getName();
strFileName = strFileName + fileName + "/";
localDirectoryPath = localDirectoryPath + "\\" + fileName;
new File(localDirectoryPath).mkdirs(); // 在本地创建目录
this.ftpClient.enterLocalPassiveMode(); // 使用被动模式设为默认
FTPFile[] allFile = this.ftpClient.listFiles(strFileName); // 获取远程文件夹中的所有子元素(包含.和..文件夹)
for (int currentFile = 0;currentFile < allFile.length;currentFile++) {
if (allFile[currentFile].isFile()) { // 判断是文件
// 调用下载文件方法
downloadFile(allFile[currentFile].getName(),localDirectoryPath,remoteDirectory);
}
}
for (int currentFile = 0;currentFile < allFile.length;currentFile++) {
if (allFile[currentFile].isDirectory()) { // 判断是文件夹
if (allFile[currentFile].getName().equals(".") || allFile[currentFile].getName().equals("..")) {
// 如果文件夹名称是 . 或者 .. 都不下载
continue;
}
String strRemoteDirectoryPath = remoteDirectory + "/" + allFile[currentFile].getName();
// 递归,调用下载文件夹方法
downLoadDirectory(localDirectoryPath,strRemoteDirectoryPath);
}
}
}
catch (IOException e) {
e.printStackTrace();
logger.info("下载文件夹失败");
return false;
}
return true;
}
}
二、测试类
package com.zyf.study_fileupload.controller;
import java.io.File;
import java.io.IOException;
public class FtpUtilTest {
public static void main(String[] args) throws IOException {
// 创建一个Ftp对象
FtpUtil ftp = new FtpUtil("43.142.67.126",21,"user","123456");
// 连接FTP服务器
ftp.ftpConnect();
// 上传文件
ftp.uploadFile(new File("F:\\test\\file\\GIF.jpg"),"/upload");
// 下载文件
ftp.downloadFile("NYY.webp","F:\\test\\download","");
// 上传文件夹(默认从FTP根路径开始)
ftp.uploadDirectory("F:\\test\\upload","");
// 下载文件夹
ftp.downLoadDirectory("F:\\test\\download","/www/wwwroot/zyf/upload");
// 关闭连接
ftp.ftpDisConnect();
}
}
注意:在Linux搭建的服务器上,从FTP下载文件夹时,通过ftpClient.listFiles(path);方法获取该目录下的所有元素(文件和文件夹)时,会自带名为 ‘.’ 和 ‘. .’ 两个文件夹,在下载文件夹时需要过滤掉这两个文件夹(此处采用if语句判断文件夹名称进行过滤,自我感觉不太好)