前段时间写过一个ftp同步信息的需求,意思就是将我们项目的iptv设备的同步信息定时生成一个csv文件并且上传到对方的ftp服务器上。第一次做这样的需求,用java操作ftp服务器,包括连接登录ftp服务器,将内容写到文件中并且上传到ftp服务器上,最后断开连接。
同步信息bean
public class FtpIptvBean {
private String region ;//所属分公司
private String stbid;//机顶盒标识 终端SN号
private String deviceVendorName;//设备厂商
private String terminalModel;//终端型号
private String mangerDate;//设备入库时间 yyyyMMddHHmmss
private String attribution;//政企/家客 在设备表中用type表示 1是家客,2 是政企(集客)
//setter/getter
}
信息同步类TerminalTestTask
//导入与ftp相关的包
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
//io流相关的包
import java.io.*;
public class TerminalTestTask {
private FTPClient ftpClient = null;
File file = new File(fileName);
//创建文件
FtpConnetUtil.createFile(file);
//需要写入文件的内容
List contentList=terminalTestTaskService.selectIptvInfo();
//省略for循环解析,将要存入文件的字段拼接起来
String contentStr =contentList.get(i).getRegion()+"|"+contentList.get(i).getStbid()+"|"+contentList.get(i).getTerminalModel()+"|"+contentList.get(i).getDeviceVendorName()+"|"+intime+"|"+attribution;
//向文件中写入内容并且换行
FtpConnetUtil.fileChaseFWNewLine(fileName, contentStr);
//通过配置文件读取ftp有关配置信息
Properties properties = FtpConnetUtil.getConnet();
String ftpurl = properties.getProperty("ftpiptvurl");
String ftpport = properties.getProperty("ftpiptvport");
String ftpusername = properties.getProperty("ftpiptvusername");
String ftppassword = properties.getProperty("ftpiptvpassword");
//服务器文件地址
String ftppath = properties.getProperty("ftpiptvpath");
//创建一个FTPClient 对象
ftpClient = new FTPClient();
//连接ftp
ftpClient.connect(ftpurl,Integer.parseInt(ftpport));
//登录ftp服务器
ftpClient.login(ftpusername, ftppassword);
//创建文件输入流
FileInputStream input = null;
//在ftp服务器上新建一个目录用于存放上传的文件
ftpClient.makeDirectory(ftppath);
//修改当前工作目录
ftpClient.changeWorkingDirectory(ftppath);
/*调用FTPClient.enterLocalPassiveMode();这个方法采用的是被动模式连接,就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。*/
ftpClient.enterLocalPassiveMode();
// FTP的传输有两种方式:ASCII传输模式和二进制数据传输模式。
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//把文件内容写入流中
input = new FileInputStream(file);
//将流写入服务器
flag = ftpClient.storeFile(file.getName(), input);
//文件上传到ftp服务器之后就断开连接退出
ftpClient.logout();
//执行关闭流操作
}
涉及到的ftp工具类
public class FtpConnetUtil {
/**
* 创建文件
* @param fileName
* @return
*/
public static boolean createFile(File fileName)throws Exception{
try{
if(!fileName.exists()){
fileName.createNewFile();
}
}catch(Exception e){
e.printStackTrace();
}
return true;
}
/**
* 写入文件,追加写入并且换行
* @param filePath
* @param content
*/
public static void fileChaseFWNewLine(String filePath, String content) {
try {
//构造函数中的第二个参数true表示以追加形式写文件
FileWriter fw = new FileWriter(filePath,true);
fw.write(content);
fw.write("\r\n"); //表示换行
fw.close();
} catch (IOException e) {
System.out.println("文件写入失败!" + e);
}
}
//读取配置文件
public static Properties getConnet() throws Exception{
Properties properties = new Properties();
InputStream is = FtpConnetUtil.class.getResourceAsStream("ftp.properties");
properties.load(is);
is.close();
return properties;
}
/**
* 获取FTPClient对象
* @param ftpHost FTP主机服务器
* @param ftpPassword FTP 登录密码
* @param ftpUserName FTP登录用户名
* @param ftpPort FTP端口 默认为21
* @return
*/
public static FTPClient getFTPClient(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort) {
FTPClient ftpClient = null;
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连接时的模式:主动模式和被动模式,以及java连接ftp时的模式设置问题。
(1) PORT(主动模式)
PORT中文称为主动模式,工作的原理: FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,客户端随机开放一个端口(1024以上),发送 PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口;FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据。
(2) PASV(被动模式)
PASV是Passive的缩写,中文成为被动模式,工作原理:FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, 客户端再连接到服务器开放的端口进行数据传输。
(3)两种模式的比较
主动模式:客户端开放端口给服务端用;被动模式:服务端开放端口给客户端用。由于很多客户端端口在防火墙内,开放端口给服务器端用比较困难。所以用被动模式的时候比较多。
(4)java中,内网用被动模式 ,外网连接时用主动模式。
FTPClient ftpClient = new FTPClient();
ftpClient.connect(url, port);
//主动模式
//ftpClient.enterLocalActiveMode();
ftpClient.enterLocalPassiveMode(); //被动模式
ftpClient.setControlEncoding("UTF-8");
ftpClient.changeWorkingDirectory(path);
参考博文:https://www.cnblogs.com/huhaoshida/p/5412615.html
https://blog.csdn.net/weixin_44706512/article/details/89281792
https://blog.csdn.net/afei3418/article/details/54375858
(中文乱码问题)https://blog.csdn.net/liquantong/article/details/74080095