package com.careye.common.ftp;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
public class FtpUtil {
private static final Logger logger = Logger.getLogger(FtpUtil.class);
public static String ftpHost = "";
public static String ftpUserName = "";
public static String ftpPassword = "";
public static int ftpPort = 1721;
/**
* 获取FTPClient对象
* @return
*/
public static FTPClient getFTPClient() {
FTPClient ftpClient = new FTPClient();
try {
ftpClient = new FTPClient();
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
logger.info("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
logger.info("FTP连接成功");
}
} catch (SocketException e) {
e.printStackTrace();
logger.info("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
logger.info("FTP的端口错误,请正确配置。");
}
return ftpClient;
}
/**
* 从FTP服务器下载文件
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param localPath 下载到本地的位置 格式:H:/download
* @param fileName FTP文件名称
*/
public static void downloadFtpFile(String ftpPath, String localPath,String fileName) {
FTPClient ftpClient = null;
try {
ftpClient = getFTPClient();
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
File localFile = new File(localPath + File.separatorChar + fileName);
OutputStream os = new FileOutputStream(localFile);
ftpClient.retrieveFile(fileName, os);
os.close();
ftpClient.logout();
logger.info("下载成功");
} catch (FileNotFoundException e) {
logger.info("没有找到" + ftpPath + "文件");
e.printStackTrace();
} catch (SocketException e) {
logger.info("连接FTP失败.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
logger.info("文件读取错误。");
e.printStackTrace();
}
}
/**
* Description: 向FTP服务器上传文件
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param fileName ftp文件名称
* @param input 文件流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String ftpPath,String fileName,InputStream input) {
boolean success = false;
FTPClient ftpClient = null;
try {
int reply;
ftpClient = getFTPClient();
reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
return success;
}
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
ftpClient.storeFile(fileName, input);
input.close();
ftpClient.logout();
success = true;
logger.info("上传成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return success;
}
/**
* 创建目录(有则切换目录,没有则创建目录)
* @param dir
* @return
*/
public static boolean createDir(String dir){
FTPClient ftpClient = null;
String d;
try {
ftpClient = getFTPClient();
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
//目录编码,解决中文路径问题
d = new String(dir.toString().getBytes("GBK"),"iso-8859-1");
//尝试切入目录
if(ftpClient.changeWorkingDirectory(d))
return true;
if(!dir.startsWith("/")){
dir = "/" + dir;
}
if(!dir.endsWith("/")){
dir = dir + "/";
}
String[] arr = dir.split("/");
StringBuffer sbfDir=new StringBuffer();
//循环生成子目录
for(String s : arr){
sbfDir.append("/");
sbfDir.append(s);
//目录编码,解决中文路径问题
d = new String(sbfDir.toString().getBytes("GBK"),"iso-8859-1");
//尝试切入目录
if(ftpClient.changeWorkingDirectory(d))
continue;
if(!ftpClient.makeDirectory(d)){
logger.info("[失败]ftp创建目录:"+sbfDir.toString());
return false;
}
logger.info("[成功]创建ftp目录:"+ sbfDir.toString());
}
//将目录切换至指定路径
return ftpClient.changeWorkingDirectory(d);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递归遍历出目录下面所有文件
*
* @param pathName 需要遍历的目录,必须以"/"开始和结束
* @throws IOException
*/
public static List<String> listFile(String pathName) throws IOException {
List<String> list = new ArrayList<String>();
if(!pathName.startsWith("/")){
pathName = "/" + pathName;
}
if(!pathName.endsWith("/")){
pathName = pathName + "/";
}
FTPClient ftpClient = null;
try {
ftpClient = getFTPClient();
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
if (pathName.startsWith("/") && pathName.endsWith("/")) {
//更换目录到当前目录
ftpClient.changeWorkingDirectory(pathName);
FTPFile[] files = ftpClient.listFiles();
for (FTPFile file : files) {
if (file.isFile()) {
list.add(pathName + file.getName());
} else if (file.isDirectory()) {
// 需要加此判断。否则,ftp默认将‘项目文件所在目录之下的目录(./)’与‘项目文件所在目录向上一级目录下的目录(../)’都纳入递归,这样下去就陷入一个死循环了。需将其过滤掉。
if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
listFile(pathName + file.getName() + "/");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
logger.info("文件:"+ JSON.toJSONString(list));
return list;
}
public static void main(String[] args) throws Exception {
// FileInputStream in =new FileInputStream(new File("D:\\Java\\commons-net-3.3.jar"));
// FtpUtil.uploadFile("/record_file", "add.jar", in);
// FtpUtil.downloadFtpFile("/record_file", "D:\\Java","add.jar");
// FtpUtil.createDir("test");
FtpUtil.listFile("/record_file");
}
}