packagecom.moy.demo.common.utils;importorg.apache.commons.lang3.StringUtils;importorg.apache.commons.net.ftp.FTP;importorg.apache.commons.net.ftp.FTPClient;importorg.apache.commons.net.ftp.FTPFile;importorg.apache.commons.net.ftp.FTPReply;import java.io.*;importjava.net.UnknownHostException;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;/***
Description: [ftp工具类]
* Created on 2018/6/4
*
*@author叶向阳
*@version1.0*/
public classFtpCli {private static final String DEFAULT_CHARSET = "UTF-8";private static final int DEFAULT_TIMEOUT = 60 * 1000;private static final String DAILY_FILE_PATH = "dailyFilePath";private finalString host;private final intport;private finalString username;private finalString password;privateFTPClient ftpClient;private volatileString ftpBasePath;privateFtpCli(String host, String username, String password) {this(host, 21, username, password, DEFAULT_CHARSET);
setTimeout(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT);
}private FtpCli(String host, intport, String username, String password, String charset) {
ftpClient= newFTPClient();
ftpClient.setControlEncoding(charset);this.host = StringUtils.isEmpty(host) ? "localhost": host;this.port = (port <= 0) ? 21: port;this.username = StringUtils.isEmpty(username) ? "anonymous": username;this.password =password;
}/***
Description:[创建默认的ftp客户端]
* Created on 2018/6/5
*
*@paramhost 主机名或者ip地址
*@paramusername ftp用户名
*@parampassword ftp密码
*@returncom.moy.demo.common.utils.FtpCli
*@author叶向阳*/
public staticFtpCli createFtpCli(String host, String username, String password) {return newFtpCli(host, username, password);
}/***
Description:[创建自定义属性的ftp客户端]
* Created on 2018/6/5
*
*@paramhost 主机名或者ip地址
*@paramport ftp端口
*@paramusername ftp用户名
*@parampassword ftp密码
*@paramcharset 字符集
*@returncom.moy.demo.common.utils.FtpCli
*@author叶向阳*/
public static FtpCli createFtpCli(String host, intport, String username, String password, String charset) {return newFtpCli(host, port, username, password, charset);
}/***
Description:[设置超时时间]
* Created on 2018/6/5
*
*@paramdefaultTimeout 超时时间
*@paramconnectTimeout 超时时间
*@paramdataTimeout 超时时间
*@author叶向阳*/
public void setTimeout(int defaultTimeout, int connectTimeout, intdataTimeout) {
ftpClient.setDefaultTimeout(defaultTimeout);
ftpClient.setConnectTimeout(connectTimeout);
ftpClient.setDataTimeout(dataTimeout);
}/***
Description:[连接到ftp]
* Created on 2018/6/5
*
*@author叶向阳*/
public void connect() throwsIOException {try{
ftpClient.connect(host, port);
}catch(UnknownHostException e) {throw new IOException("Can't find FTP server :" +host);
}int reply =ftpClient.getReplyCode();if (!FTPReply.isPositiveCompletion(reply)) {
disconnect();throw new IOException("Can't connect to server :" +host);
}if (!ftpClient.login(username, password)) {
disconnect();throw new IOException("Can't login to server :" +host);
}//set data transfer mode.
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//Use passive mode to pass firewalls.
ftpClient.enterLocalPassiveMode();
initFtpBasePath();
}/***
Description:[连接ftp时保存刚登陆ftp时的路径]
* Created on 2018/6/6
*
*@author叶向阳*/
private void initFtpBasePath() throwsIOException {if(StringUtils.isEmpty(ftpBasePath)) {synchronized (this) {if(StringUtils.isEmpty(ftpBasePath)) {
ftpBasePath=ftpClient.printWorkingDirectory();
}
}
}
}/***
Description:[ftp是否处于连接状态,是连接状态返回true]
* Created on 2018/6/5
*
*@returnboolean 是连接状态返回true
*@author叶向阳*/
public booleanisConnected() {returnftpClient.isConnected();
}/***
Description:[上传文件到对应日期文件下,
* 如当前时间是2018-06-06,则上传到[ftpBasePath]/[DAILY_FILE_PATH]/2018/06/06/下]
* Created on 2018/6/6
*
*@paramfileName 文件名
*@paraminputStream 文件输入流
*@returnjava.lang.String
*@author叶向阳*/
public String uploadFileToDailyDir(String fileName, InputStream inputStream) throwsIOException {
changeWorkingDirectory(ftpBasePath);
SimpleDateFormat dateFormat= new SimpleDateFormat("/yyyy/MM/dd");
String formatDatePath= dateFormat.format(newDate());
String uploadDir= DAILY_FILE_PATH +formatDatePath;
makeDirs(uploadDir);
storeFile(fileName, inputStream);return formatDatePath + "/" +fileName;
}/***
Description:[根据uploadFileToDailyDir返回的路径,从ftp下载文件到指定输出流中]
* Created on 2018/6/6
*
*@paramdailyDirFilePath 方法uploadFileToDailyDir返回的路径
*@paramoutputStream 输出流
*@author叶向阳*/
public void downloadFileFromDailyDir(String dailyDirFilePath, OutputStream outputStream) throwsIOException {
changeWorkingDirectory(ftpBasePath);
String ftpRealFilePath= DAILY_FILE_PATH +dailyDirFilePath;
ftpClient.retrieveFile(ftpRealFilePath, outputStream);
}/***
Description:[获取ftp上指定文件名到输出流中]
* Created on 2018/6/5
*
*@paramftpFileName 文件在ftp上的路径 如绝对路径 /home/ftpuser/123.txt 或者相对路径 123.txt
*@paramout 输出流
*@author叶向阳*/
public void retrieveFile(String ftpFileName, OutputStream out) throwsIOException {try{
FTPFile[] fileInfoArray=ftpClient.listFiles(ftpFileName);if (fileInfoArray == null || fileInfoArray.length == 0) {throw new FileNotFoundException("File '" + ftpFileName + "' was not found on FTP server.");
}
FTPFile fileInfo= fileInfoArray[0];if (fileInfo.getSize() >Integer.MAX_VALUE) {throw new IOException("File '" + ftpFileName + "' is too large.");
}if (!ftpClient.retrieveFile(ftpFileName, out)) {throw new IOException("Error loading file '" + ftpFileName + "' from FTP server. Check FTP permissions and path.");
}
out.flush();
}finally{
closeStream(out);
}
}/***
Description:[将输入流存储到指定的ftp路径下]
* Created on 2018/6/6
*
*@paramftpFileName 文件在ftp上的路径 如绝对路径 /home/ftpuser/123.txt 或者相对路径 123.txt
*@paramin 输入流
*@author叶向阳*/
public void storeFile(String ftpFileName, InputStream in) throwsIOException {try{if (!ftpClient.storeFile(ftpFileName, in)) {throw new IOException("Can't upload file '" + ftpFileName + "' to FTP server. Check FTP permissions and path.");
}
}finally{
closeStream(in);
}
}/***
Description:[根据文件ftp路径名称删除文件]
* Created on 2018/6/6
*
*@paramftpFileName 文件ftp路径名称
*@author叶向阳*/
public void deleteFile(String ftpFileName) throwsIOException {if (!ftpClient.deleteFile(ftpFileName)) {throw new IOException("Can't remove file '" + ftpFileName + "' from FTP server.");
}
}/***
Description:[上传文件到ftp]
* Created on 2018/6/6
*
*@paramftpFileName 上传到ftp文件路径名称
*@paramlocalFile 本地文件路径名称
*@author叶向阳*/
public void upload(String ftpFileName, File localFile) throwsIOException {if (!localFile.exists()) {throw new IOException("Can't upload '" + localFile.getAbsolutePath() + "'. This file doesn't exist.");
}
InputStream in= null;try{
in= new BufferedInputStream(newFileInputStream(localFile));if (!ftpClient.storeFile(ftpFileName, in)) {throw new IOException("Can't upload file '" + ftpFileName + "' to FTP server. Check FTP permissions and path.");
}
}finally{
closeStream(in);
}
}/***
Description:[上传文件夹到ftp上]
* Created on 2018/6/6
*
*@paramremotePath ftp上文件夹路径名称
*@paramlocalPath 本地上传的文件夹路径名称
*@author叶向阳*/
public void uploadDir(String remotePath, String localPath) throwsIOException {
localPath= localPath.replace("\\\\", "/");
File file= newFile(localPath);if(file.exists()) {if (!ftpClient.changeWorkingDirectory(remotePath)) {
ftpClient.makeDirectory(remotePath);
ftpClient.changeWorkingDirectory(remotePath);
}
File[] files=file.listFiles();if (null !=files) {for(File f : files) {if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
uploadDir(remotePath+ "/" +f.getName(), f.getPath());
}else if(f.isFile()) {
upload(remotePath+ "/" +f.getName(), f);
}
}
}
}
}/***
Description:[下载ftp文件到本地上]
* Created on 2018/6/6
*
*@paramftpFileName ftp文件路径名称
*@paramlocalFile 本地文件路径名称
*@author叶向阳*/
public void download(String ftpFileName, File localFile) throwsIOException {
OutputStream out= null;try{
FTPFile[] fileInfoArray=ftpClient.listFiles(ftpFileName);if (fileInfoArray == null || fileInfoArray.length == 0) {throw new FileNotFoundException("File " + ftpFileName + " was not found on FTP server.");
}
FTPFile fileInfo= fileInfoArray[0];if (fileInfo.getSize() >Integer.MAX_VALUE) {throw new IOException("File " + ftpFileName + " is too large.");
}
out= new BufferedOutputStream(newFileOutputStream(localFile));if (!ftpClient.retrieveFile(ftpFileName, out)) {throw new IOException("Error loading file " + ftpFileName + " from FTP server. Check FTP permissions and path.");
}
out.flush();
}finally{
closeStream(out);
}
}/***
Description:[改变工作目录]
* Created on 2018/6/6
*
*@paramdir ftp服务器上目录
*@returnboolean 改变成功返回true
*@author叶向阳*/
public booleanchangeWorkingDirectory(String dir) {if (!ftpClient.isConnected()) {return false;
}try{returnftpClient.changeWorkingDirectory(dir);
}catch(IOException e) {
}return false;
}/***
Description:[下载ftp服务器下文件夹到本地]
* Created on 2018/6/6
*
*@paramremotePath ftp上文件夹路径名称
*@paramlocalPath 本地上传的文件夹路径名称
*@returnvoid
*@author叶向阳*/
public void downloadDir(String remotePath, String localPath) throwsIOException {
localPath= localPath.replace("\\\\", "/");
File file= newFile(localPath);if (!file.exists()) {
file.mkdirs();
}
FTPFile[] ftpFiles=ftpClient.listFiles(remotePath);for (int i = 0; ftpFiles != null && i < ftpFiles.length; i++) {
FTPFile ftpFile=ftpFiles[i];if (ftpFile.isDirectory() && !ftpFile.getName().equals(".") && !ftpFile.getName().equals("..")) {
downloadDir(remotePath+ "/" + ftpFile.getName(), localPath + "/" +ftpFile.getName());
}else{
download(remotePath+ "/" + ftpFile.getName(), new File(localPath + "/" +ftpFile.getName()));
}
}
}/***
Description:[列出ftp上文件目录下的文件]
* Created on 2018/6/6
*
*@paramfilePath ftp上文件目录
*@returnjava.util.List
*@author叶向阳*/
public List listFileNames(String filePath) throwsIOException {
FTPFile[] ftpFiles=ftpClient.listFiles(filePath);
List fileList = new ArrayList<>();if (ftpFiles != null) {for (int i = 0; i < ftpFiles.length; i++) {
FTPFile ftpFile=ftpFiles[i];if(ftpFile.isFile()) {
fileList.add(ftpFile.getName());
}
}
}returnfileList;
}/***
Description:[发送ftp命令到ftp服务器中]
* Created on 2018/6/6
*
*@paramargs ftp命令
*@author叶向阳*/
public void sendSiteCommand(String args) throwsIOException {if (!ftpClient.isConnected()) {
ftpClient.sendSiteCommand(args);
}
}/***
Description:[获取当前所处的工作目录]
* Created on 2018/6/6
*
*@returnjava.lang.String 当前所处的工作目录
*@author叶向阳*/
publicString printWorkingDirectory() {if (!ftpClient.isConnected()) {return "";
}try{returnftpClient.printWorkingDirectory();
}catch(IOException e) {//do nothing
}return "";
}/***
Description:[切换到当前工作目录的父目录下]
* Created on 2018/6/6
*
*@returnboolean 切换成功返回true
*@author叶向阳*/
public booleanchangeToParentDirectory() {if (!ftpClient.isConnected()) {return false;
}try{returnftpClient.changeToParentDirectory();
}catch(IOException e) {//do nothing
}return false;
}/***
Description:[返回当前工作目录的上一级目录]
* Created on 2018/6/6
*
*@returnjava.lang.String 当前工作目录的父目录
*@author叶向阳*/
publicString printParentDirectory() {if (!ftpClient.isConnected()) {return "";
}
String w=printWorkingDirectory();
changeToParentDirectory();
String p=printWorkingDirectory();
changeWorkingDirectory(w);returnp;
}/***
Description:[创建目录]
* Created on 2018/6/6
*
*@parampathname 路径名
*@returnboolean 创建成功返回true
*@author叶向阳*/
public boolean makeDirectory(String pathname) throwsIOException {returnftpClient.makeDirectory(pathname);
}/***
Description:[创建多个目录]
* Created on 2018/6/6
*
*@parampathname 路径名
*@author叶向阳*/
public void makeDirs(String pathname) throwsIOException {
pathname= pathname.replace("\\\\", "/");
String[] pathnameArray= pathname.split("/");for(String each : pathnameArray) {if(StringUtils.isNotEmpty(each)) {
ftpClient.makeDirectory(each);
ftpClient.changeWorkingDirectory(each);
}
}
}/***
Description:[关闭流]
* Created on 2018/6/6
*
*@paramstream 流
*@author叶向阳*/
private static voidcloseStream(Closeable stream) {if (stream != null) {try{
stream.close();
}catch(IOException ex) {//do nothing
}
}
}/***
Description:[关闭ftp连接]
* Created on 2018/6/6
*
*@author叶向阳*/
public voiddisconnect() {if (null != ftpClient &&ftpClient.isConnected()) {try{
ftpClient.logout();
ftpClient.disconnect();
}catch(IOException ex) {//do nothing
}
}
}
}