Java中实现ftp下载文件至本地(详细)

Java中实现ftp下载文件至本地(详细):

2020-09-13:今天记录一下java中实现ftp下载文件至本地的功能模块,同此与大家交流分享有什么不对的地方大家可以指出!

1.FTP协议:

什么是FTP呢?FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写。 该协议是Internet文件传送的基础,它由一系列规格说明文档组成,目标是提高文件的共享性,提供非直接使用远程计算机,使存储介质对用户透明 和可靠高效地传送数据。简单的说,FTP就是完成两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载 (download)”文件。若将文件从自己计算机中拷贝至远程计算机上,则称之为“上载(upload)”文件。

2.SSH工具

ssh---ftp----winscp----filezilla-----xftp----

上面呢简单介绍下ftp协议和一些使用的工具,这篇文章呢我在java中是用的sftp下载,那使用的类是ChannelSftp,言归正传,奉上自己的demo。。。。

呵呵

1.连接

 protected static Logger log = LoggerFactory.getLogger(FTPUtil.class);

    public static final String NO_FILE = "No such file";

    private ChannelSftp sftp = null;

    private Session sshSession = null;

    /* FTP账号 */
    private String username;
    /* FTP密码 */
    private String password;
    /* FTP主机 */
    private String host;
    /* FTP端口 */
    private int port;

    public FTPUtil(String host, int port, String username, String password) {
    
    
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 连接sftp服务器
     *
     * @return ChannelSftp sftp类型
     * @throws Exception
     */
    public ChannelSftp connect() throws FtpException {
    
    
        log.info("尝试连接FTP {host=" + host + ",username=" + username + ",port=" + port + "}");
        boolean connect = false;
        JSch jsch = new JSch();
        try {
    
    
            int tryCountAll = 5;
            int tryCount = 0;
            while (tryCount++ < tryCountAll && !connect) {
    
    
                if (tryCount > 1) {
    
    
                    try {
    
    
                        Thread.sleep(5000 * (tryCount - 1));
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    log.info("第" + tryCount + "次尝试连接FTP服务器");
                }
                sshSession = jsch.getSession(username, host, port);
                sshSession.setPassword(password);
                Properties properties = new Properties();
                properties.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(properties);
                sshSession.connect(50000);
                Channel channel = sshSession.openChannel("sftp");
                channel.connect(50000);
                sftp = (ChannelSftp) channel;
                if (sftp == null) {
    
    
                    log.info("FTP 服务器未连接");
                    connect = false;
                } else {
    
    
                    log.info("连接 FTP 成功!");
                    connect = true;
                }
            }
        } catch (JSchException e) {
    
    
            throw new FtpException("连接 FTP 异常 : " + e.getMessage());
        }
        return sftp;
    }

这一块呢我们走完了第一步,先去连接远程,代码中加了重试的逻辑(重新连接的意思),代码中一些类大家可以下去自行了解,本人就不啰嗦了哦(我这边使用的是ChannelSftp ,大家不妨可以试试另一个FtpClient这个类(大步骤都差不多)

2.批量下载(我这里就不啰嗦很多了直接贴了代码,大家可以搜其他的,比如删除,单个下载什么的有很多,我这里项目用到的是一个批量下载,所以就贴出了一段代码!

public void createDirectoryQuietly(File file) {
    
    
        if (file != null) {
    
    
            if (!file.exists()) {
    
    
                if (!file.mkdirs()) {
    
    
                    throw new RuntimeException(file.getName() + " is invalid,can't be create directory");
                }
            }
        }
    }

	//remoteDir 是FTP上要下载的目录
	// localFile 是下载的本地目录
    public File downloadFileNew(String remoteDir, String localFile) throws FtpException {
    
    
        long startTime = System.currentTimeMillis();
        connect();  //连接ftp
        log.info("开始下载文件FTP目录 " + remoteDir + " 本地文件 " + localFile);
        File file = null;
        file = new File(localFile);
       /* if (file.exists()) {

            deleteFileAll(file);
        }
        file.mkdirs();*/
        createDirectoryQuietly(file);//创建目录文件,(这个方法可以创建目录,但多层级的我没试,大家定义路径的时候可以 /home/test  home是本来就有的test会创建)
        OutputStream output = null;
        try {
    
    

            /***
             * 得到custInfo路径下所有文件名
             */
            sftp.cd(remoteDir);  //进入remoteDir目录
            String path = remoteDir + "/custInfo";
            Vector v = sftp.ls(path);   //获取custInfo下文件列表
            List<String> filenameNew = new ArrayList<>(); //获取custInfo下所有目录文件名
            if (v.size() > 0) {
    
    
                log.info("文件个数不为0,开始下载。。。。。。。。。filesize=" + v.size());
                Iterator it = v.iterator();
                while (it.hasNext()) {
    
       //循环文件
                    ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
                    String filenames = lsentry.getFilename();
                    if (!".".equals(filenames) && !"..".equals(filenames)) {
    
    
                        log.info(path + "路径下的文件名" + filenames);
                        filenameNew.add(filenames);
                    }
                }
            } else {
    
    
                log.info("获取文件失败 " + remoteDir + "文件数为0");
                throw new FtpException("获取文件失败 " + remoteDir + "文件数为0");
            }

            /***
             * 得到custInfo/路径下各个文件下的文件名
             */
            sftp.cd(path);  //切换到custInfo/路径下
            for (int i = 0; i < filenameNew.size(); i++) {
    
      //得到每个目录文件下的文件
                System.out.println(filenameNew.get(i) + "文件名");
                Vector<?> vNew = sftp.ls(filenameNew.get(i));  //获取文件列表
                sftp.cd(filenameNew.get(i)); //切换到custInfo/路径下各个文件路径下
                File file2=new File(localFile+"/"+filenameNew.get(i));
                if (file2.exists()) {
    
    
                    file2.delete();
                }
                file2.mkdir();
                if (vNew.size() > 0) {
    
    
                    Iterator it = vNew.iterator();
                    while (it.hasNext()) {
    
    
                        ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
                        String filenames1 = lsentry.getFilename();
                        if (!".".equals(filenames1) && !"..".equals(filenames1)) {
    
    
                            log.info(filenameNew.get(i) + "路径下的文件名" + filenames1);
                            File file1 = new File(file2+"/"+filenames1);
                            file1.createNewFile();
                            output = new FileOutputStream(file1);
                            sftp.get(filenames1, output);
                            log.info("文件:" + filenames1 + " 下载成功.");
                        }
                    }
                    sftp.cd(path);  //每次路径下载后再切换到 上一级目录
                }
            }
        } catch (SftpException e) {
    
    
            if (e.toString().equals(NO_FILE)) {
    
    
                log.info("下载文件失败");
                throw new FtpException("下载文件失败");
            }
            throw new FtpException("ftp目录或者文件异常,检查ftp目录和文件" + e.toString());
        } catch (FileNotFoundException e) {
    
    
            throw new FtpException("本地目录异常,请检查" + file.getPath() + e.getMessage());
        } catch (IOException e) {
    
    
            throw new FtpException("创建本地文件失败" + file.getPath() + e.getMessage());
        } finally {
    
    
            if (output != null) {
    
    
                try {
    
    
                    output.close();
                } catch (IOException e) {
    
    
                    throw new FtpException("Close stream error." + e.getMessage());
                }
            }
            disconnect();
        }
        log.info("下载文件结束 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
        return file;
    }

给大家解释下代码

在这里插入图片描述

第一句 sftp.cd()这个方法大家都知道,cd进去目录(注意:关键点大家注意一下:当你想操作某个目录文件时一定要cd到这个目录下(啰嗦,跟谁不知道一样

第三句 sfpt.ls()这个方法,大家也都知道哈,查看文件。往后代码的话就是使用循环将目录下的文件名循环出来,我这边使用list集合存了起来(注意:因为我当时要取得文件是 多层级目录的大家如果不是多层级的话,直接走你逻辑就好。)

在这里插入图片描述
这样的多层级目录的!

第二段代码

在这里插入图片描述
这一段呢,顾名思义,因为我的第一段代码呢是获取多层级的目录名字,那么这一段就是获取多层级目录下的文件。注意:上面代码的最后一段 那个cd方法。操作多层级目录你每进去一个目录,然后换另一个的话你就要在代码里,在cd下一个目录路径!

今天的这个ftp下载分享完了,大家如果有什么不太懂的地方,欢迎评论提出,我这会秒回哦!也谢谢大家的支持!记录生活,记录知识!我是王不正

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_46379371/article/details/108562278
今日推荐