Java 实现FTP 和SFTP链接下载文件 并处理出现的org.apache.commons.net.MalformedServerReplyException: Could not parse

咸利
2023-12-01

Java 实现FTP 和SFTP链接下载文件

并处理出现的org.apache.commons.net.MalformedServerReplyException: Could not parse response code.Server Reply: SSH-2.0-OpenSSH异常

由于项目中要从云服务器中获取实时的图片,故需要开发此功能,所以记录一下

我首先用的是

FTP链接

  1. 导入maven依赖commons-net
<dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.8.0</version>
 </dependency>
  1. 实现工具类 由于我只需要下载功能就实现下载

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.nio.charset.Charset;
    
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPFile;
    public class FileUtil  {
    
         //ftp对象
        private static FTPClient ftp;
        //需要连接到的ftp端的ip
        private String ip;
        //连接端口,默认21
        private int port;
        //要连接到的ftp端的名字
        private String name;
        //要连接到的ftp端的对应得密码
        private String password;
    
       
        public ftp1(String ip, int port, String name, String password) {
            ftp = new FTPClient();
            this.ip = ip;
            this.port = port;
            this.name = name;
            this.password = password;
    
            //验证登录
            try {
                ftp.connect(ip, port);
                System.out.println(ftp.login(name, password));
                ftp.setCharset(Charset.forName("UTF-8"));
                ftp.setControlEncoding("UTF-8");
                System.out.println("链接成功");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
        //下载文件的第二种方法,优化了传输速度
            public void getFile2() {
                try {
                    InputStream is = ftp.retrieveFileStream("zhuye.html");
                    System.out.println("读取成功");
                    FileOutputStream fos = new FileOutputStream(new File("D:/zhuye.html"));
    
                    byte[] b = new byte[1024];
                    int len = 0;
                    while ((len = is.read(b)) != -1) {
                        fos.write(b,0,len);
                    }
                    System.out.println("输出成功");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    
        public static void main(String args[]) {
            String ip="";//临时域名
            String username="";//用户名
            String password="";//密码
    
            ftp1 m = new ftp1(ip,21,username,password);
           m.getFilesName();
        }
    }
    
    

    注:结果在登录时一直出错

    org.apache.commons.net.MalformedServerReplyException: Could not parse response code.
    Server Reply: SSH-2.0-OpenSSH
    

百度后发现是Java后台是通过org.apache.commons.net.ftp.FTPClient 连接服务器,进行FTP操作

报错原因

我们使用FileZilla软件链接服务器(FTP或者SFTP)都是能够成功链接的。区别是链接的参数中

我仔细查看了FileZilla在链接时的ip为:sftp://112.74.109.xx

但是在Java后台使用org.apache.commons.net.ftp.FTPClient通过协议SSH2进行SFTP连接时就会报如上错误,原因是它不支持这种方式的连接(使用FTPSClient的SSL也是不行的)。

我的解决办法

使用 com.jcraft.jsch.ChannelSftp 代替org.apache.commons.net.ftp.FTPClient

SFTP链接

  1. 导入maven依赖com.jcraft
<dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
</dependency>

2.实现工具类

public class FileUtil {
    //用户名
    private String username;
     //密码
    private String password;
     //ip
    private String host;
     //端口一般为22
    private int port;
    //私钥
    private String privateKey;
    
    ChannelSftp sftp = null;
	//通过构造方法传参
   public FileUtil(String username, String password, String host, int port){
       this.username = username;
       this.password = password;
       this.host = host;
       this.port = port;
   }
    public FileUtil(String username, String host, int port, String privateKey){
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }
	//登录,检查链接情况
    public void login(){
        try {
            JSch jSch = new JSch();
            if(privateKey != null){
                jSch.addIdentity(privateKey);
            }
            Session session = jSch.getSession(username,host,port);
            if(password != null){
                session.setPassword(password);
            }
            session.setTimeout(100000);

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            Channel channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            System.out.println("登录成功");
        } catch (JSchException e) {
            e.printStackTrace();
        }

    }
    //上传文件
    /**
     * @param basePath 目标路径
     * @param direcotry 目标子路径
     * @param sftpFileName 文件名称
     */ 
    public void  upload(String basePath, String direcotry, String sftpFileName, InputStream inputStream) throws SftpException{
        try {
            //进入到目标目录
            sftp.cd(basePath);
            sftp.cd(direcotry);
        } catch (SftpException e) {
            String[] dirs = direcotry.split("/");
            String temPath = basePath;
            for (String dir: dirs
                 ) {
                if( null == dir || "".equals(dir)) continue;
                temPath +="/" + dir;
                try {
                    sftp.cd(temPath);
                } catch (SftpException ex) {
                    sftp.mkdir(temPath);
                    sftp.cd(temPath);
                }
            }
        }
        sftp.put(inputStream,sftpFileName);
        System.out.println("上传成功");
    }
    //下载文件
    /**
     * @param directory 下载的文件路径
     * @param downloadFile 下载的文件名
     * @param saveFileDirectory 保存的文件路径
     */
    public void download(String directory, String downloadFile, String saveFileDirectory) throws SftpException, FileNotFoundException{
       if(directory != null && !"".equals(directory)){
           sftp.cd(directory);
       }
        String saveFile = saveFileDirectory + "//" + downloadFile;
       File file = new File(saveFile);
       sftp.get(downloadFile, new FileOutputStream(file));
        System.out.println("下载成功");
    }
    //登出




    public static void main(String[] args) throws FileNotFoundException,SftpException {
        FileUtil fiel = new FileUtil("root","XXXXXX","112.74.109.XX",22);
        fiel.login();     
        //测试上传功能
        File file = new File("D:\\image\\1.jpg");
        InputStream is = new FileInputStream(file);
        fiel.upload("/usr/local/image","","1.jpg",is);
        //测试下载功能
        try {
            fiel.download("/usr/local/image/","1.jpg","D:\\image");
        } catch (SftpException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

总结

在登录服务器时卡了很久,没有搞清楚到底是SFTP还是FTP

接下来需要实现按时间下载文件夹下的每个图片

 类似资料: