java操作ftp实现文件上传

前段时间写过一个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

你可能感兴趣的:(java操作ftp实现文件上传)