FTPClient实现ftp的上传下载(包含中文文件名和中文路径问题)

整理一个ftp上传下载的工具类,转编码的问题经测试都已经很好的解决,我这里用的ftp为Windows系统下,Linux下的ftp操作写法不一样,下次有用到再整理:


FtpUtil

  • jar commons-net-3.3.jar
  • maven依赖

    commons-net
    commons-net
    3.1
public class FtpUtil {  

    private final static Log logger = LogFactory.getLog(FtpUtil.class);  

    /** 
     * 获取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 = new FTPClient();  
        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服务器下载文件 
     *  
     * @param ftpHost FTP IP地址 
     *  
     * @param ftpUserName FTP 用户名 
     *  
     * @param ftpPassword FTP用户名密码 
     *  
     * @param ftpPort FTP端口 
     *  
     * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa 
     *  
     * @param localPath 下载到本地的位置 格式:H:/download 
     *  
     * @param fileName 文件名称 
     */  
    public static void downloadFtpFile(String ftpHost, String ftpUserName,  
            String ftpPassword, int ftpPort, String ftpPath, String localPath,  
            String fileName) {  

        FTPClient ftpClient = null;  

        try {  
            String ftpPath2 = new String(ftpPath.getBytes("GBK"),"iso-8859-1");
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);  
            ftpClient.setControlEncoding("UTF-8"); // 中文支持  
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);  
            ftpClient.enterLocalPassiveMode();  
            boolean flag1 = ftpClient.changeWorkingDirectory(ftpPath2); 
            if (!flag1) {
                logger.error("没有找到" + ftpPath + "---该路径");
                return;
            }
            File localFile = new File(localPath + File.separatorChar + new String(fileName.getBytes("GBK"),"UTF-8"));  
            OutputStream os = new FileOutputStream(localFile);  
            //复制文件流
            boolean flag2 = ftpClient.retrieveFile(new String(fileName.getBytes("GBK"),"iso-8859-1"), os); 
            if (!flag2) {
                logger.error("没有找到" + fileName + "---该文件");
                localFile.delete();
            }
            os.close();  
            ftpClient.logout();  

        } catch (FileNotFoundException e) {  
            logger.error("没有找到" + ftpPath + "文件");  
            e.printStackTrace();  
        } catch (SocketException e) {  
            logger.error("连接FTP失败.");  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
            logger.error("文件读取错误。");  
            e.printStackTrace();  
        }  

    }  
    /**
    * 上传部分代码如下:
    * @param ftpHost:文件服务器主机地址
    * @param ftpPort:文件服务器端口号
    * @param ftpUserName:用户名
    * @param ftpPassword:密码
    * @param path:文件要保存的路径
    * @param filename:文件名字
    * @param localPath:本地文件路径
    * @return
    */
    public static void uploadToFTPServer(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String path,
            String filename, String localPath) {
        FTPClient ftpClient = null; // 创建一个客户端实例
        try {
            path = new String(path.getBytes("GBK"),"iso-8859-1");
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort); 
            // ftp.makeDirectory("bbb");//创建文件目录
            ftpClient.changeWorkingDirectory(path);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 设置文件以二进制的形式上传,防止文件内容乱码出现
            // 设置文件名字的编码格式为iso-8859-1,因为FTP上传的时候默认编码为iso-8859-1,解决文件名字乱码的问题
            filename = new String(filename.getBytes("GBK"), "iso-8859-1");

            InputStream in = new FileInputStream(new File(localPath));
            ftpClient.storeFile(filename, in); // 开始上传文件
            in.close();// 关闭文件输入流
            ftpClient.logout();// 断开和ftp服务器之间的连接
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
    }

    public static String getFullCurrentWorkingDirectory(FTPClient ftpClient) throws IOException{
        String[] dir = ftpClient.doCommandAsStrings("pwd","");
        System.out.println(dir[0]);
        Pattern p=Pattern.compile("\"(.*?)\"");  
        Matcher m=p.matcher(dir[0]);
        String fullPath = null;
        if(m.find()){
            fullPath = m.group(0).replace("\"","");
        }
        return fullPath;
    }

    public static String getRelativeCurrentWorkingDirectory(FTPClient ftpClient) throws IOException{
        String[] dir = ftpClient.doCommandAsStrings("pwd","");
        System.out.println(dir[0]);
        return "";
    }

    public static void showFile(FTPClient ftpClient) throws IOException{
        FTPFile[] files = ftpClient.listFiles();
        for(FTPFile f : files){
            if(f.isDirectory()){
                System.out.println(f.getName()+"-----directory");
                ftpClient.changeWorkingDirectory(f.getName());
                showFile(ftpClient);
            }else if(f.isFile()){
                System.out.println(f.getName());
            }
        }
        ftpClient.changeToParentDirectory();
    }

}  

需要几个坑

  1. ftp的路径出错或文件不存在的情况话下载会出现空文件,我这里的处理方式也很简单,失败即删了本地新建的文件。
  2. 中文路径和中文文件名的处理情况不太一样,iso-8859-1是ftp默认的编码格式,路径转换了就行,但是文件名要特别注意的是下载时,new本地文件时给的文件名一定得是中文,而retrieveFile进行ftp文件操作时得转换编码对应。
  3. setFileType的方式可有效防止文件内容乱码

你可能感兴趣的:(ftp)