最近在做一个上传下载对账单功能,其中部分用到了ftpclient这个类(已解决中文乱码问题),分享出来。顺便看看自己写的有没有缺点。
1.首先你需要在http://mvnrepository.com/下载或者引入:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version><!--版本号请随意-->
</dependency>
然后复制下面的类到你的工程中(代码中包含了连接时间的监控):
package com.wz.ftpclient;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTP;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FtpClient {
private static Logger log = LoggerFactory.getLogger(FtpClient.class);
private String host;
private int port;
private String username;
private String password;
private FTPClient ftp = new FTPClient();
/**
* @param host ip地址
* @param port 端口号
* @param username 用户名
* @param password 密码
*/
public FtpClient(String host, int port, String username, String password) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
//有必要进行设置
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
conf.setServerLanguageCode("zh"); //解决文件名的中文乱码问题
ftp.setControlEncoding("GBK"); //编码问题请自己调试一下
ftp.configure(conf);
}
/**
* 连接ftp服务器
* @return
*/
private boolean connectFtp() {
boolean flag = false;
int reply;
try {
long startLogin = System.currentTimeMillis();
ftp.connect(host, port);// 连接ftp服务器
log.info("连接:" + host + ":" + port);
ftp.login(username, password);// 登录
log.info("登录:" + username + password);
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
log.info("登陆失败");
return false;
}
flag = true;
long endLogin = System.currentTimeMillis();
log.info("登录成功,登录耗时:" + (endLogin - startLogin) + "ms");
log.info("开启被动模式");
ftp.enterLocalPassiveMode();
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.setFileTransferMode(FTP.BINARY_FILE_TYPE);
} catch (IOException e) {
log.error("连接异常,请检查地址和端口", e);
}
return flag;
}
/**
* 登出
* @return
*/
private boolean logOut() {
long logOutTime = System.currentTimeMillis();
boolean flag = false;
try {
if (ftp != null) flag = ftp.logout();
} catch (IOException e) {
log.error("登出异常", e);
} finally{
try {
ftp.disconnect();
} catch (IOException e) {
log.error("disconnect异常", e);
}
}
long endLogOutTime = System.currentTimeMillis();
log.info("登出耗时:" + (endLogOutTime - logOutTime) + "ms");
return flag;
}
/**
* 上传文件
* @param path ftp服务器的文件路径
* @param filename 保存文件名
* @param inputStream 文件流
* @return
*/
private boolean uploadFile(String path, String filename, InputStream inputStream) {
boolean flag = false;
if (connectFtp()) {
try {
log.info("Remote system is " + ftp.getSystemType());
if (!makeDirectory(path)){ //创建路径,你必须先创建/a/b,再创建/a/b/c
log.info("创建目录【" + path + "】失败");
return false;
} else ftp.changeWorkingDirectory(path);
ftp.enterLocalPassiveMode();
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
flag = ftp.storeFile(filename, inputStream);
if (flag == true) {
log.info("上传成功");
} else {
log.info("上传失败");
}
} catch (SocketException e) {
log.error("Socket异常", e);
} catch (IOException e) {
log.error("io异常", e);
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (IOException e) {
log.error("io异常", e);
}
logOut();
}
}
return flag;
}
private boolean makeDirectory(String path) throws IOException{
String[] paths = getEntirelyPath(path);
for (int j = 0; j < paths.length; j++) {
if (!ftp.changeWorkingDirectory(paths[j])){
if (!ftp.makeDirectory(paths[j])){
log.info("创建目录" + paths[j] + "失败");
return false;
}
}
}
return true;
}
/**
* 获得完全的路径集合
* 比如 参数 path=/a/b/c/d/ 得到 String[] = '/','/a/','/a/b/','/a/b/c/','/a/b/c/d/'
* @param path
* @return
*/
private static String[] getEntirelyPath(String path){
String[] pathArray = path.split("/");
String[] paths = new String[pathArray.length];
int j = 0;
StringBuilder p = new StringBuilder();
for (int i = 0; i < pathArray.length; i++) {
paths[j] = p.append(pathArray[i]).append("/").toString();
j++;
}
return paths;
}
/**
* 上传文件
* @param path ftp服务器的文件路径
* @param filename 文件名
* @param sourcePath 要上传的文件路径
* @return
*/
public boolean uploadFile(String path, String filename, String sourcePath) {
boolean flag = false;
File file = new File(sourcePath);
if (file.exists() && file.isFile()) {
try {
FileInputStream fis = new FileInputStream(file);
flag = uploadFile(path, filename, fis);
} catch (FileNotFoundException e) {
log.error("File异常", e);
}
} else {
log.error("文件不存在或者该文件是文件夹");
}
return flag;
}
/**
*
* @param downloadPath 保存到本地的路径
* @param remotePath 远程路径
* @param remoteFilenames 远程文件集合
* @return
*/
public boolean downloadFile(String downloadPath, String remotePath, String[] remoteFilenames) {
boolean downloadFlag = false;
if (connectFtp()) {
long startDownloadTime = System.currentTimeMillis();
try {
if (ftp.changeWorkingDirectory(remotePath)) {
log.info("当前目录:" + ftp.printWorkingDirectory());
long singleDownTime = 0;
long writeFileTime = 0;
long startMatchTime = System.currentTimeMillis();
for (String remoteFilename : remoteFilenames) {
long startDownloadFile = System.currentTimeMillis();
InputStream inputStream = ftp.retrieveFileStream(remoteFilename);
long endDownloadFile = System.currentTimeMillis();
log.info("下载文件" + remoteFilename + "耗时:" + (endDownloadFile - startDownloadFile) + "ms");
singleDownTime = endDownloadFile - startDownloadFile;
if (inputStream == null) {
log.info("无法下载文件:" + remoteFilename);
continue;
} else {
log.info("下载的文件是:" + remoteFilename);
}
long startWriteFileTolocal = System.currentTimeMillis();
OutputStream output = new FileOutputStream(new File(downloadPath + remoteFilename));
byte[] bytes = new byte[1024];
int i = -1;
try {
while ((i = inputStream.read(bytes)) != -1) {
output.write(bytes, 0, i);
}
output.flush();
downloadFlag = true;
} catch (IOException e) {
log.error("IO异常", e);
} finally {
inputStream.close();
ftp.completePendingCommand();
output.close();
}
long endWriteFileTolocal = System.currentTimeMillis();
writeFileTime += (endWriteFileTolocal - startWriteFileTolocal);
}
long endMatchTime = System.currentTimeMillis();
log.info("文件匹配耗时:" + (endMatchTime - startMatchTime - singleDownTime - writeFileTime)+ "ms");
log.info("写入文件耗时:" + writeFileTime + "ms");
}
} catch (IOException e) {
log.error("切换工作目录报错!", e);
}
long endDownloadTime = System.currentTimeMillis();
log.info("下载所有文件加匹配耗时:" + (endDownloadTime - startDownloadTime) + "ms");
logOut();
}
return downloadFlag;
}
/**
* 罗列某个路径下的所有文件和子路径
* @param path
* @return
* @throws IOException
*/
public FTPFile[] listFiles(String path) throws IOException{
if (connectFtp()) {
try {
log.info("Remote system is " + ftp.getSystemType());
log.info("查看路径:" + path);
return ftp.listFiles(path);
} catch (Exception e) {
log.error("查询ftp目录异常", e);
} finally {
logOut();
}
}
return new FTPFile[0];
}
/**
* 罗列某两个路径下的所有文件和子路径
* 可以改造成-不定参类型 String... path
* @param pathA
* @param pathB
* @return
* @throws IOException
*/
public FTPFile[] listFiles(String pathA, String pathB) throws IOException{
if (connectFtp()) {
try {
log.info("Remote system is " + ftp.getSystemType());
log.info("查看路径:" + pathA);
FTPFile[] fileA = ftp.listFiles(pathA);
FTPFile[] fileB = ftp.listFiles(pathB);
FTPFile[] totalFiles = new FTPFile[fileA.length+fileB.length];
System.arraycopy(fileA, 0, totalFiles, 0, fileA.length);
System.arraycopy(fileB, 0, totalFiles, fileA.length, fileB.length);
return totalFiles;
} catch (Exception e) {
log.error("查询ftp目录异常", e);
} finally {
logOut();
}
}
return new FTPFile[0];
}
public static void main(String[] args) {
FtpClient ftpClient = new FtpClient("127.0.0.1", 21, "a", "b");
//上传
ftpClient.uploadFile("/a/b/c/d/", "1.txt", "D://tmp//1.txt");
//下载
ftpClient.downloadFile("D://tmp//", "/a/b/c/d/", new String[]{"1.txt","2.txt"});
}
}
亲测可用,如有需要,你直接copy即可。如果有什么问题,你可以评论或私信我。