正所谓工欲善其事必先利其器,熟悉了下一套流程,以此铭记。
1.FTP服务搭建
由于本人使用wondiow系统,所以针对window的童鞋们可以查看。至于windowX这里配置类似,所以不要纠结于window系统不同。经过以上操作我们可以获取到ftp的用户名,密码,以及IP地址,端口号(ps:默认端口号,搭建时可以设置)
2.FTP编码集问题
由于FTP使用编码集为ISO-8859-1,所以在中文文件夹以及文件名称上传,获取服务器文件等会出现问题。有以下2中解决方案:
1.将目录、文件转码,这样就造成跟目录、文件相关的都要转码,以至于
ftpClient.changeWorkingDirectory(new String(onepath.getBytes("GBK"),"iso-8859-1"));
ftpClient.storeFile(new String(fileName.getBytes("GBK"),"iso-8859-1"), in);
ftpClient.listFiles(new String(remotePath.getBytes("GBK"),"iso-8859-1"));
那这样岂不是很麻烦,而且每次使用都需要转码,有没有更简单的呢?有,请看第2中
2.设置相应编码集等信息
ftpClient = new FTPClient();
ftpClient.setControlEncoding("GBK");
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);//系统类型 这表示window系统
conf.setServerLanguageCode("zh");
ftpClient.configure(conf);
ftpClient.connect(this.ip, this.port);
这边需要注意的是顺序必须这么写
3.工具类相关
1.Jar包问题
由于本人使用maven,pom中的配置
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.5</version>
<classifier>ftp</classifier>
</dependency>
2.工具类开发
import org.apache.commons.net.ftp.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.*;
import java.util.Arrays;
import java.util.List; /**
* FTP上传工具类
*/
public class FtpUtil {
private static Logger log = LoggerFactory.getLogger(FtpUtil.class);
private final static String FILE_SEPARATOR = System.getProperties().getProperty("file.separator");
private String ip;
private String username;
private String password;
private int port = 21;
private FTPClient ftpClient = null; public FtpUtil(String serverIP, String username, String password) {
this.ip = serverIP;
this.username = username;
this.password = password;
} public FtpUtil(String serverIP, int port, String username, String password) {
this.ip = serverIP;
this.username = username;
this.password = password;
this.port = port;
} /**
* 连接ftp服务器
*/
public boolean connectServer() {
boolean result = true;
try {
ftpClient = new FTPClient();
ftpClient.setControlEncoding("GBK");
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
ftpClient.configure(conf);
ftpClient.connect(this.ip, this.port);
ftpClient.login(this.username, this.password);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
result = false;
}
} catch (IOException e) {
e.printStackTrace();
log.error("连接ftp服务器失败", e);
result = false;
}
return result;
} /**
* 断开与ftp服务器连接
*/
public boolean closeServer() {
try {
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
return true;
} catch (IOException e) {
log.error("断开与ftp服务器连接失败", e);
return false;
}
} /**
* 向FTP根目录上传文件
*
* @param localFile
* @param newName 文件名称
* @throws Exception
*/
public boolean uploadFile(String localFile, String newName) {
boolean success = false;
InputStream input = null;
try {
File file = null;
if (checkFileExist(localFile)) {
file = new File(localFile);
}
input = new FileInputStream(file);
success = ftpClient.storeFile(newName, input);
} catch (Exception e) {
log.error("FTP根目录上传文件上传失败(ps:传入文件名)", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
log.error("FTP根目录上传文件上传(ps:传入文件名),输入流关闭失败", e);
}
}
}
return success;
} /**
* 向FTP根目录上传文件
*
* @param input
* @param newName 新文件名
* @throws Exception
*/
public boolean uploadFile(InputStream input, String newName) {
boolean success = false;
try {
success = ftpClient.storeFile(newName, input);
} catch (Exception e) {
log.error("FTP根目录上传文件上传失败(ps:传入文件流)", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
log.error("FTP根目录上传文件上传(ps:传入文件流),输入流关闭失败", e);
}
}
}
return success;
} /**
* 向FTP指定路径上传文件
*
* @param localFile
* @param newName 新文件名
* @param remoteFoldPath
* @throws Exception
*/
public boolean uploadFile(String localFile, String newName, String remoteFoldPath) {
InputStream input = null;
boolean success = false;
try {
// 改变当前路径到指定路径
if (!this.changeDirectory(remoteFoldPath)) {
return false;
}
File file = null;
if (checkFileExist(localFile)) {
file = new File(localFile);
}
input = new FileInputStream(file);
success = ftpClient.storeFile(newName, input);
} catch (Exception e) {
log.error("FTP指定路径上传文件失败(ps:本地文件路径以及ftp服务器中文件名)", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
log.error("FTP指定路径上传文件失败(ps:本地文件路径以及ftp服务器中文件名),输入流关闭失败", e);
}
}
}
return success;
} /**
* 向FTP指定路径上传文件
*
* @param input
* @param newName 新文件名
* @param remoteFoldPath
* @throws Exception
*/
public boolean uploadFile(InputStream input, String newName, String remoteFoldPath) throws Exception {
boolean success = false;
try {
// 改变当前路径到指定路径
if (!this.changeDirectory(remoteFoldPath)) {
return false;
}
success = ftpClient.storeFile(newName, input);
} catch (Exception e) {
log.error("FTP指定路径上传文件失败(ps:本地文件流及ftp服务器中文件名)", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error("FTP指定路径上传文件失败(ps:本地文件流及ftp服务器中文件名),输入流关闭失败", e);
}
}
}
return success;
} /**
* 从FTP服务器下载文件
*
* @param remotePath FTP路径(不包含文件名)
* @param fileName 下载文件名
* @param localPath 本地路径
*/
public boolean downloadFile(String remotePath, String fileName, String localPath) {
BufferedOutputStream output = null;
boolean success = false;
try {
// 检查本地路径
if (!this.checkFileExist(localPath)) {
return false;
}
// 改变工作路径
if (!this.changeDirectory(remotePath)) {
return false;
}
// 列出当前工作路径下的文件列表
List<FTPFile> fileList = this.getFileList();
if (fileList == null || fileList.size() == 0) {
return false;
}
for (FTPFile ftpfile : fileList) {
if (ftpfile.getName().equals(fileName)) {
File localFilePath = new File(localPath + File.separator + ftpfile.getName());
output = new BufferedOutputStream(new FileOutputStream(localFilePath));
success = ftpClient.retrieveFile(ftpfile.getName(), output);
}
}
} catch (Exception e) {
log.error("FTP服务器下载文件失败", e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
log.error("FTP服务器下载文件,输出流关闭失败", e);
}
}
}
return success;
} /**
* 从FTP服务器获取文件流
*
* @param remoteFilePath
* @return
* @throws Exception
*/
public InputStream downloadFile(String remoteFilePath) {
try {
return ftpClient.retrieveFileStream(remoteFilePath);
} catch (IOException e) {
log.error("FTP服务器获取文件流失败", e);
}
return null;
} /**
* 获取FTP服务器上[指定路径]下的文件列表
*
* @param remotePath
* @return
*/
public List<FTPFile> getFtpServerFileList(String remotePath) {
try {
FTPListParseEngine engine = ftpClient.initiateListParsing(remotePath);
return Arrays.asList(engine.getNext(25));
} catch (IOException e) {
log.error("获取FTP服务器上[指定路径]下的文件列表(getFtpServerFileList)失败", e);
}
return null;
} /**
* 获取FTP服务器上[指定路径]下的文件列表
*
* @param remotePath
* @return
*/
public List<FTPFile> getFileList(String remotePath) {
List<FTPFile> ftpfiles = null;
try {
ftpfiles = Arrays.asList(ftpClient.listFiles(remotePath));
} catch (IOException e) {
log.error("获取FTP服务器上[指定路径]下的文件列表(getFileList)失败", e);
}
return ftpfiles;
} /**
* 获取FTP服务器[当前工作路径]下的文件列表
*
* @return
*/
public List<FTPFile> getFileList() {
List<FTPFile> ftpfiles = null;
try {
ftpfiles = Arrays.asList(ftpClient.listFiles());
} catch (IOException e) {
log.error("获取FTP服务器[当前工作路径]下的文件列表失败", e);
}
return ftpfiles;
} /**
* 改变FTP服务器工作路径
*
* @param remoteFoldPath
*/
public boolean changeDirectory(String remoteFoldPath) {
boolean result = false;
try {
result = ftpClient.changeWorkingDirectory(new String(remoteFoldPath));
} catch (IOException e) {
log.error("改变FTP服务器工作路径失败", e);
}
return result;
} /**
* 删除文件
*
* @param remoteFilePath
* @return
* @throws Exception
*/
public boolean deleteFtpServerFile(String remoteFilePath) {
boolean result = false;
try {
result = ftpClient.deleteFile(remoteFilePath);
} catch (IOException e) {
log.error("FTP服务器删除文件失败", e);
}
return result;
} /**
* 删除目录
*
* @param remoteFoldPath
* @return
* @throws Exception
*/
public boolean deleteFold(String remoteFoldPath) {
boolean result = false;
try {
result = ftpClient.removeDirectory(remoteFoldPath);
} catch (IOException e) {
log.error("FTP服务器删除目录失败", e);
}
return result;
} /**
* 删除目录以及文件
*
* @param remoteFoldPath
* @return
*/
public boolean deleteFoldAndsubFiles(String remoteFoldPath) {
boolean success = false;
List<FTPFile> list = this.getFileList(remoteFoldPath);
if (list == null || list.size() == 0) {
return deleteFold(remoteFoldPath);
}
for (FTPFile ftpFile : list) {
String name = ftpFile.getName();
if (ftpFile.isDirectory()) {
success = deleteFoldAndsubFiles(remoteFoldPath + FILE_SEPARATOR + name);
} else {
success = deleteFtpServerFile(remoteFoldPath + FILE_SEPARATOR + name);
}
if (!success) {
break;
}
}
if (!success) {
return false;
}
success = deleteFold(remoteFoldPath);
return success;
} /**
* 创建目录
*
* @param remoteFoldPath
* @return
*/
public boolean createFold(String remoteFoldPath) {
boolean result = false;
try {
result = ftpClient.makeDirectory(remoteFoldPath);
} catch (IOException e) {
log.error("FTP服务器创建目录失败", e);
}
return result;
} /**
* 检查本地路径是否存在
*
* @param filePath
* @return
* @throws Exception
*/
public boolean checkFileExist(String filePath) {
return new File(filePath).exists();
} /**
* 把文件移动到特定目录下
*
* @param remoteFile
* @param remoteNewPath
* @return
*/
public boolean moveFtpServerFile(String remoteFile, String remoteNewPath) {
boolean result = false;
try {
result = ftpClient.rename(remoteFile, remoteNewPath);
} catch (IOException e) {
log.error("FTP服务器文件移动失败", e);
}
return result;
} /**
* 判断是文件还是目录
*
* @param remoteOldPath
* @return
*/
public boolean isContents(String remoteOldPath) {
return changeDirectory(remoteOldPath);
} /**
* 递归创建远程服务器目录
*
* @param dirpath 远程服务器文件绝对路径
* @return 目录创建是否成功
*/
public void createDirecroty(String dirpath) {
String directory = dirpath.substring(0, dirpath.lastIndexOf("/") + 1);
try {
if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(new String(directory))) {
// 如果远程目录不存在,则递归创建远程服务器目录
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
while (true) {
String subDirectory = new String(dirpath.substring(start, end));
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
}
}
start = end + 1;
end = directory.indexOf("/", start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}
} catch (IOException e) {
log.error("递归生成目录失败", e);
}
} /**
* 复制
*
* @param remoteOldPath
* @param remoteNewPath
* @return
*/
public boolean copyFtpServerFile(String remoteOldPath, String remoteNewPath) {
boolean copyFalg = false;
List<FTPFile> filelist;
try {
ftpClient.enterLocalPassiveMode();
filelist = this.getFileList(remoteOldPath);
int length = filelist == null || filelist.isEmpty() ? 0 : filelist.size();
String category = null;
ByteArrayOutputStream fos = null;
ByteArrayInputStream in = null;
if (length > 0) {
boolean flage = false;
if (this.isContents(remoteOldPath)) {
flage = true;
}
changeDirectory("/");
for (FTPFile ftpFile : filelist) {
category = ftpFile.getName();
if (ftpFile.isFile()) {
// 如果是文件则复制文件
ftpClient.setBufferSize(1024);
fos = new ByteArrayOutputStream();
copyFalg = ftpClient.retrieveFile(flage ? remoteOldPath + FILE_SEPARATOR + category : remoteOldPath, fos);
if (!copyFalg) {
return copyFalg;
}
// 如果读取的文件流不为空则复制文件
if (fos != null) {
in = new ByteArrayInputStream(fos.toByteArray());
copyFalg = ftpClient.storeFile(remoteNewPath + FILE_SEPARATOR + category, in);
// 关闭文件流
fos.close();
in.close();
if (!copyFalg) {
return copyFalg;
}
}
} else if (ftpFile.isDirectory()) {
// 如果是目录则先创建该目录
copyFalg = this.createFold(remoteNewPath + FILE_SEPARATOR + category);
// 再进入子目录进行递归复制
copyFtpServerFile(remoteOldPath + FILE_SEPARATOR + category, remoteNewPath + FILE_SEPARATOR + category);
}
}
}
} catch (IOException e) {
log.error("文件复制失败", e);
copyFalg = false;
}
return copyFalg;
} public static void main(String[] args) {
FtpUtil ftpUtil = new FtpUtil("", "", "");
//执行文件移动
/*if (ftpUtil.connectServer()) {
if (ftpUtil.changeDirectory("load")) {
ftpUtil.moveFtpServerFile("xlsj_h1_v0.7.apk", ".." + FILE_SEPARATOR + "down" + FILE_SEPARATOR + "1.apk");
ftpUtil.closeServer();
}
}*/
//复制 xlsj_h1_v0.8.apk是目录 xlsj_h1_v0.7.apk是文件
/* if (ftpUtil.connectServer()) {
ftpUtil.copyFtpServerFile("load/xlsj_h1_v0.8.apk", "down");
ftpUtil.copyFtpServerFile("load/xlsj_h1_v0.8.apk/xlsj_h1_v0.7.apk", "down");
ftpUtil.closeServer();
}*/ if (ftpUtil.connectServer()) {
ftpUtil.copyFtpServerFile("load/安卓上传包/安卓开发包.apk", "down");
ftpUtil.closeServer();
}
}
}
参考:
http://blog.csdn.net/iheng_scau/article/details/41682511
http://blog.163.com/biangji_and/blog/static/3382923020102491050525/
http://bbs.csdn.net/topics/390373219
http://commons.apache.org/proper/commons-net/javadocs/api-1.4.1/org/apache/commons/net/ftp/FTPClient.html
http://yangyangmyself.iteye.com/blog/1299997