java-FTP
总结一下工作中用到的,ftp传输文件的操作案例。
一、设计思路
java中实现ftp传输的开源jar包邮很多,这里推荐commons-net包下面的ftp工具类,用起来简单,用的人也多。下面粘贴一段源码,我们可以从这个方法点进去可以看到这个类中上传文件需要的参数,一个是文件名,一个是输入流。
public boolean storeFile(String remote, InputStream local)
所以我们的思路大概是:
(1)创建一个方法或工具类,将所需要传输的信息转化成输入流。
(2)传建一个命名方法或工具类,返回值是String,用于按照命名规则生成文件名。
(3)引入配置文件工具类,把连接服务器所需的信息,比如ftp登录用户名、密码、端口号等等,写在配置文件中,方便更改,降低代码的耦合性。
(4)引入log4j日志工具类方便排查异常。
(5)单元测试,编写main方法用于测试。
二、引入maven依赖
<!--ftp工具--> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency> <!--日志--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.1.2</version> <scope>test</scope> </dependency>
三、代码编写
(1)上传文件类
public class FtpFileUpload {
/**
* 日志
*/
private static final Logger logger = LoggerFactory.getLogger(FtpFileUpload.class);
/**
* IP地址
*/
private String ftpServerIp;
/**
* 端口号
*/
private int ftpServerPort;
/**
* 用户名称
*/
private String userName;
/**
* 密码
*/
private String passWord;
/**
* FTP服务器保存目录
*/
private String ftpFilePath;
public FtpFileUpload() {
}
public FtpFileUpload(String ftpServerIp, int ftpServerPort,
String userName, String passWord, String ftpFilePath) {
this.ftpFilePath = ftpFilePath;
this.ftpServerIp = ftpServerIp;
this.userName = userName;
this.passWord = passWord;
this.ftpServerPort = ftpServerPort;
}
public boolean execute(InputStream in,String fileName) {
boolean flag=false;
FTPClient ftpClient = new FTPClient();
ftpClient.setControlEncoding("utf-8");
try {
ftpClient.connect(ftpServerIp, ftpServerPort);
if (ftpClient.login(userName, passWord)) {
//如果没有目录就创建
if(!ftpClient.changeWorkingDirectory(ftpFilePath)){
ftpClient.makeDirectory(ftpFilePath);
}
ftpClient.changeWorkingDirectory(ftpFilePath);
flag=ftpClient.storeFile(fileName, in);
if (flag){
logger.info("ftp上传文件成功!"+fileName+ftpFilePath);
}else{
logger.info("ftp上传文件失败!"+fileName+ftpFilePath);
}
in.close();
ftpClient.logout();
} else {
logger.info("用户名或密码错误,用户名:"+userName+"密码:"+passWord);
ftpClient.disconnect();
}
} catch (SocketException e) {
e.printStackTrace();
logger.info(e.getMessage()+"连接ftp服务器失败,可能是地址错误");
} catch (IOException e){
e.printStackTrace();
logger.info(e.getMessage()+"连接ftp服务器失败,可能是端口错误");
}finally {
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
return flag;
}
/**
* @return the ftpServerIp
*/
public String getFtpServerIp() {
return ftpServerIp;
}
/**
* @param ftpServerIp
* the ftpServerIp to set
*/
public void setFtpServerIp(String ftpServerIp) {
this.ftpServerIp = ftpServerIp;
}
/**
* @return the ftpServerPort
*/
public int getFtpServerPort() {
return ftpServerPort;
}
/**
* @param ftpServerPort
* the ftpServerPort to set
*/
public void setFtpServerPort(int ftpServerPort) {
this.ftpServerPort = ftpServerPort;
}
/**
* @return the userName
*/
public String getUserName() {
return userName;
}
/**
* @param userName
* the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* @return the passWord
*/
public String getPassWord() {
return passWord;
}
/**
* @param passWord
* the passWord to set
*/
public void setPassWord(String passWord) {
this.passWord = passWord;
}
/**
* @return the ftpFilePath
*/
public String getFtpFilePath() {
return ftpFilePath;
}
/**
* @param ftpFilePath
* the ftpFilePath to set
*/
public void setFtpFilePath(String ftpFilePath) {
this.ftpFilePath = ftpFilePath;
}
}
(2)这里写了个main方法进行测试,也可以用junit
public class FtpUploadTest {
/**
* 日志
*/
private static final Logger logger = LoggerFactory.getLogger(FtpUploadTest.class);
public static void main(String args[]){
logger.info("");
long start,end;
start = System.currentTimeMillis();
try{
//要传输的内容和文件名
String transInfo = "abc";
String filename = "abc.txt";
//将其转化为输入流
InputStream in = tranToYLStream(transInfo);
//上传文件
FtpFileUpload ftpFileUpload = getFtpFileUpload();
ftpFileUpload.execute(in,filename);
}catch (Exception e){
logger.error(e.getMessage());
}
end = System.currentTimeMillis();
logger.info("FTP上传文件成功,耗时:"+(end-start)+"ms");
}
private static FtpFileUpload getFtpFileUpload() {
/**
* 从配置文件获取ftp服务器信息
*/
String ftpUri = PropertyUtil.getParam("offline.test.ftp.uri");
Integer ftpPort = Integer.valueOf(PropertyUtil.getParam("offline.test.ftp.port"));
String ftpUserId = PropertyUtil.getParam("offline.test.ftp.username");
String ftpPassword = PropertyUtil.getParam("offline.test.ftp.password");
String ftpPath = PropertyUtil.getParam("offline.test.ftp.ftpPath");
FtpFileUpload ftpFileUpload = new FtpFileUpload(ftpUri,ftpPort,ftpUserId,ftpPassword,ftpPath);
return ftpFileUpload;
}
/**
* 将要传输的信息转化为输入流
*/
public static InputStream tranToYLStream(String transInfo) {
StringBuffer sb = new StringBuffer(transInfo);
sb.append(System.getProperty("line.separator"));
InputStream inputStream = new ByteArrayInputStream(sb.toString().getBytes());
return inputStream;
}
}
四、使用总结
这种写法虽然简单,但是有几个致命的缺陷,一个是字符串超长问题,如果是在项目中,很可能是几万条数据的信息,这么长的字符串会很占用内存。另外就是用这种方式传输如果数据量很大,速度就会很慢,在网上查了也没有找到解决的办法。学艺不精,仍需继续努力啊!