项目场景:
项目要求将指定文件上传至FTP、判断FTP是否存在指定文件、从FTP下载指定文件
工具类代码:
需要依赖org.apache.commons.net包
package com.lotso.web.module.ffzp.utils;
import lombok.Data;
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 org.apache.commons.net.ftp.FTPReply;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.SocketException;
import java.util.Calendar;
/***
* @author : Cirno
* @Date : 2022/8/16 13:56
* @description :
* @modifyied By :
*/
@Data
@Slf4j
public class FTPDealUtils {
private FTPClient ftpClient = null;
private String Host = null; // ftp 主机Host
private String UserName = null;
private String Password = null;
private int Port = 21;
public FTPDealUtils() {
log.info("begin");
}
/**
* 初始化
*
* @param host FTP服务器地址
* @param username 服务名
* @param password 密码
* @param port 端口号
*/
public FTPDealUtils(String host, String username, String password, int port) {
this.Host = host;
this.UserName = username;
this.Password = password;
this.setPort(port);
}
/**
* 创建FTP连接
*/
public boolean connectServer() {
boolean flag = true;
ftpClient = new FTPClient();
int reply;
try {
ftpClient.connect(Host);
ftpClient.login(UserName, Password);
log.info("Connected to " + Host);
log.info(ftpClient.getReplyString());
reply = ftpClient.getReplyCode();
// 将文件传输类型设置为二进制
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//防止server超时断开
ftpClient.setDataTimeout(120000);
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
log.error("FTP server refused connection.");
flag = false;
}
} catch (SocketException e) {
flag = false;
log.error("异常:",e);
log.info("登录ftp服务器 " + Host + " 失败,连接超时!");
} catch (IOException e) {
flag = false;
log.error("异常:",e);
log.info("登录ftp服务器 " + Host + " 失败,FTP服务器无法打开!");
}
log.info("登陆ftp服务器成功" + Host);
return flag;
}
public void disConnect() {
closeConnect();
}
/**
* 关闭连接
*/
private void closeConnect() {
try {
if (ftpClient != null) {
ftpClient.disconnect();
}
} catch (Exception e) {
log.error("异常:",e);
}
}
/**
* 从FTP下载文件
* @param path 远程目录
* @param fileName 文件名称
* @param response 将文件绑定到response中,供用户在页面下载
* @return
*/
public boolean downFile(String path,String fileName, HttpServletResponse response) {
try {
OutputStream fos = null;
long currTime = Calendar.getInstance().getTimeInMillis();
if (connectServer()) {
//校验路径与文件名
if (StringUtils.isEmpty(fileName)) {
log.info("FTP文件下载的远程文件未指定!!");
return false;
}
if (StringUtils.isEmpty(path)) {
log.info("FTP文件下载 的本地存储文件路径为空!");
return false;
}
//切换路径
if (!checkRemoteFile(path, fileName)) {
return false;
}
//
fos = response.getOutputStream();
//下载文件到本地
ftpClient.setBufferSize(1024);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.retrieveFile(fileName, fos);
log.info(ftpClient.getReplyString());
fos.flush();
fos.close();
closeConnect();
long currTime2 = Calendar.getInstance().getTimeInMillis();
long diff2 = currTime2 - currTime;
log.info("所用时间为=" + diff2);
}
} catch (Exception ex) {
log.error("异常:",ex);
log.info("下载文件失败!!!!");
return false;
}
return true;
}
/**
* 参数说明:
* localStr:本地目录+文件名,都用绝对路径
* remoteStr = 远程目录+文件名,如果要取的文件直接在登陆后的默认目录下,这里远程目录可以不要 remoteStr = /文件名;
*/
public boolean ApacheFTPDownFile(String localStr, String remoteStr) {
try {
FileOutputStream fos = null;
Calendar cCalendar = Calendar.getInstance();
long currTime = cCalendar.getTimeInMillis();
if (connectServer()) {
/*得到相应的目录和远程文件*/
int i = 0;
i = remoteStr.lastIndexOf("/");
String currDir = remoteStr.substring(0, i);
String Remotefile = remoteStr.substring(i + 1);
if (remoteStr.equals("")) {
log.info("请输入正确的文件名!");
return false;
}
if (!checkRemoteFile(currDir, Remotefile)) {
return false;
}
// 若本地路径不存在则生成路径
checkLocalDir(localStr);
//下载文件到本地
File file = new File(localStr);
fos = new FileOutputStream(file);
ftpClient.retrieveFile(Remotefile, fos);
log.info(ftpClient.getReplyString());
fos.flush();
fos.close();
closeConnect();
cCalendar = Calendar.getInstance();
long currTime2 = cCalendar.getTimeInMillis();
long diff2 = currTime2 - currTime;
log.info("所用时间为=" + diff2);
}
} catch (Exception ex) {
log.error("异常:",ex);
log.info("下载文件失败!!!!");
return false;
}
return true;
}
private void checkLocalDir(String localStr) {
File formatPath = null;
int j = localStr.lastIndexOf("\\");
String localDir = localStr.substring(0, j);
formatPath = new File(localDir);
if (!formatPath.exists()) {
formatPath.mkdirs();
}
}
/**
* 查询FTP指定目录下指定的文件是否存在
* @param patch 远程文件路径
* @param fileName 远程文件名称
* @return
*/
public boolean checkFTPFile(String patch,String fileName) {
return checkRemoteFile(patch, fileName);
}
/**
* 对远程文件进行分析
* @param cFileDir
* @param cFileName
* @return
*/
private boolean checkRemoteFile(String cFileDir, String cFileName) {
try {
boolean tFlag = false;
tFlag = ftpClient.changeWorkingDirectory(cFileDir);
if (!tFlag) {
log.info("请检查:[" + cFileDir + "]路径是否正确");
return false;
}
log.info(ftpClient.printWorkingDirectory());
log.info(ftpClient.getReplyString());
FTPFile ff[] = ftpClient.listFiles();
boolean fileExist = false;
if (ff == null || ff.length == 0) {
log.info("该目录下无任何文件!");
return false;
} else {
log.info("该目录下有文件!length:" + ff.length);
for (int j = 0; j < ff.length; j++) {
if (ff[j].getName().equals(cFileName)) {
log.info("在FTP目录上找到了文件!");
fileExist = true;
break;
}
}
}
if (!fileExist) {
log.info("在FTP目录下没有读取到文件");
return false;
}
return true;
} catch (Exception ex) {
log.error("异常:",ex);
try {
if (ftpClient != null) {
ftpClient.disconnect();
}
} catch (Exception e) {
log.error("异常:",e);
}
return false;
}
}
public void upFile(String path, String filename, String localFilePath) {
FileInputStream in = null;
try {
this.connectServer();
in = new FileInputStream(new File(localFilePath));
ftpClient.changeWorkingDirectory(path);
ftpClient.storeFile(filename, in);
in.close();
} catch (Exception e) {
log.error("异常:",e);
}finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
log.error("异常:",e);
}
}
}
}
/**
* 上传文件
*
* @param file 文件
* @param path 上传服务器路径
* @return
*/
public boolean ApacheFTPUploadFile(File file, String path) {
try {
if (!file.isFile()) {
//不是文件
return false;
} else if (!fileSize(file)) {
//控制文件大小
return false;
}
if (!connectServer()) {
return false;
}
//转到path路径
path = this.pathAddress(path);
ftpClient.makeDirectory(path);
//进入服务器目录
if (!ftpClient.changeWorkingDirectory(path)) {
log.info("上载路径出错");
return false;
}
//给文件加上时间撮,防止服务器文件重复
String fileName = file.getName();
try {
FileInputStream fis = new FileInputStream(file);
if (!ftpClient.storeFile(fileName, fis)) {
closeConnect();
fis.close();
return false;
}
fis.close();
} catch (IOException e) {
log.error("异常:",e);
return false;
} finally {
closeConnect();
}
} catch (IOException e) {
log.error("异常:",e);
return false;
}
return true;
}
/**
* 控制文件的大小,默认为5M
*
* @param file_in 文件
*/
private boolean fileSize(File file_in) {
return this.fileSize(file_in, 5);
}
/**
* 控制文件的大小
*
* @param file_in 文件
* @param size 文件大小,单位为M
*/
private boolean fileSize(File file_in, int size) {
if (file_in == null || file_in.length() == 0) {
//文件为空
return false;
} else {
if (file_in.length() > (1024 * 1024 * size)) {
//文件大小不能大与size
return false;
}
}
return true;
}
/**
* 格式化文件路径 检查path最后有没有分隔符'\'
*
* @param path
* @return
*/
public String pathAddress(String path) {
if (path == null || path.length() < 1) {
return "";
}
String temp_path = path.substring(path.length() - 1);
if (!temp_path.equals("/") && !temp_path.equals("\\")) {
temp_path = path + File.separator;
} else {
temp_path = path;
}
return temp_path;
}
public void save(byte[] pBytes, String pName, String pPath) {
if (!pPath.endsWith("/")) {
pPath = pPath + "/";
}
StringBuffer mFilePath = new StringBuffer(pPath);
File mFileDir = new File(mFilePath.toString());
if ((!mFileDir.exists()) &&
(!mFileDir.mkdirs())) {
log.info("创建目录失败!" + mFileDir.getPath());
return;
}
FileOutputStream tFos = null;
try {
tFos = new FileOutputStream(mFilePath.toString() + pName);
tFos.write(pBytes);
} catch (IOException ex) {
log.info("保存文件失败!");
}finally {
if (tFos != null){
try {
tFos.close();
} catch (IOException e) {
log.error("异常:",e);
}
}
}
}
}