JAVA FTPClient——远程文件操作

来源:互联网 发布:idc国际数据公司 编辑:程序博客网 时间:2024/05/18 20:12

Preface:最近忙的一个query理解服务的项目,关于分词工具的问题,升级为使用北京侧的分词工具,属于工程性质的。其中,需要加载动态库和model文件夹,而且,由于服务部署到多台机器上,为此,动态库和model文件夹不能直接放到代码上带过去,而是放到FTP机器上,当服务部署到多个机器或者机器扩容的时候,避免手工操作文件,而是在服务启动的时候,通过java FTPClient自动把文件拉到服务所在的机器,然后在代码里面加载动态库和Model,拿到分词句柄。每来了一个请求,通过该分词句柄对这个请求里面的query进行分词。


一、FTPClient所需包

基本上使用apache的jar包,在代码中import即可

import org.apache.commons.net.ftp.FTPClient;

import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

说明:

FTPClient:用于连接机器

FTPFile:用于解析FTP机器上文件夹中的文件

FTPReply:用于判断是否连接成功

二、FTP连接

    FTPClient ftpClient = new FTPClient();    try {                //连接FTP                ftpClient.connect(ftpHost, ftpPort);            } catch (SocketException e) {                e.printStackTrace();                LOGGER.info("FTP的IP地址可能错误,请正确配置。");            } catch (IOException e) {                e.printStackTrace();                LOGGER.info("hose port可能有问题");            }            try {                ftpClient.login(username, password);            } catch (IOException e) {                e.printStackTrace();                LOGGER.info("FTP账号密码可能有问题");            }            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {                LOGGER.info("未连接到FTP,用户名或密码错误");            } else {                LOGGER.info("FTP连接成功");            }
逻辑流程:

是否需要连接FTP:判断动态库和model文件夹在机器上,则需要连接FTP

连接FTP:主机名、端口号、账号、密码(卤煮用FTP机器的ip代替主机名,使用了主机名反而不行)

是否连接成功:FTPReply

注意:端口号为FTP端口号,非机器端口号(可能不同,多试下)

三、FTPClient传输

代码

try{            ftpClient.changeWorkingDirectory(remotePath);            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//传输的时候以二进制传输,一定要加这行,不然(文件变小)天大的坑!!!            FTPFile[] fs = ftpClient.listFiles();            for(FTPFile ff : fs){                File localFile = new File(localPath + ff.getName());                if(ff.isDirectory()){                    //将路径改到子文件夹,对子文件夹进行下载                    ftpClient.changeWorkingDirectory(remotePath+ff.getName());                    FTPFile[] fsubs = ftpClient.listFiles();                    for(FTPFile fsubf : fsubs){                        //创建子文件夹                        File localSublDir = new File(localPath + ff.getName());                        if(!localSublDir.exists()){                            localSublDir.mkdir();                        }                        //获取子文件夹里面的子文件的名字                        File localSubFile = new File(localPath + ff.getName() +"/"+ fsubf.getName());                        OutputStream is = new FileOutputStream(localSubFile);                        ftpClient.retrieveFile(fsubf.getName(), is);                        is.close();                    }                    ftpClient.changeWorkingDirectory(remotePath);                }else{                    OutputStream is = new FileOutputStream(localFile);                    ftpClient.retrieveFile(ff.getName(), is);                    is.close();                }            }        } catch (IOException e) {            e.printStackTrace();        }

说明

changeWorkingDirectory():定位到FTP机器上文件夹的位置

setFileType():设置FTP传输类型。最好使用二进制传输,另外还有传输编码格式(utf-8)设置等,不设置的话,传输后的文件可能有所变化,使用不了了,天大的坑!!!

listFiles():将文件夹里面的文件遍历出来

localFile:本地File名

is:将File转为文件流

retrieveFile():将这个文件写到这个文件流中

注:

由于卤煮的文件夹里还有文件夹,两层,为此,需要进入子文件夹进行传输,不然的话,子文件夹里的文件传输不过去;当文件夹多层的时候,需要递归传输。

有的时候,可能涉及权限问题。从FTP机器上的某个路径传到另外一个机器只读的路径下,setReadable、setWritable俩函数似乎根本没用。咋整的话,只能mkdir(),然后读到创建的路径下比较好。