java连接Sftp服务器后,使用第三方jar com.jcraft.jsch.ChannelSftp;用get()方法获取的InputStream流为空
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java连接Sftp服务器后,使用第三方jar com.jcraft.jsch.ChannelSftp;用get()方法获取的InputStream流为空相关的知识,希望对你有一定的参考价值。
1.工程使用spring mvc框架
2.第三方jar包为最新版本
3.工程部署在Linux服务器上,文件服务器与web服务器为相同服务器
4.可以正常使用sftp上传文件至指定目录
问题:目前使用的get(String src)方法模式为根据传入的sftp服务器文件绝对路径返回一个文件流,现在返回的值为空,但是采用get(String src,String dst)模式却可以文件成功复制到指定目录,测试环境均为本地计算机,环境为windows + eclipse.现在求解答使用模式一的方法为何获取不到指定文件流
返回的文件流为空不代表null,指返回的文件流data内容为[0],是无效数据流
一帮垃圾,真正的技术点从来没有得到解决过,相对比知乎差了十万八千里
闹呢,如果有时间去看源码我还用这么着急发布求助吗,我现在是寻求有经验的人给我个意见,不是需要一个人来告诉我排错方法
参考技术A 同问,请问解决了么? 参考技术B 同样碰到这个问题 想问下解决了吗?我的代码库-Java8实现FTP与SFTP文件上传下载
有网上的代码,也有自己的理解,代码备份
一般连接windows服务器使用FTP,连接linux服务器使用SFTP。linux都是通过SFTP上传文件,不需要额外安装,非要使用FTP的话,还得安装FTP服务(虽然刚开始我就是这么干的)。
另外就是jdk1.8和jdk1.7之前的方法有些不同,网上有很多jdk1.7之前的介绍,本篇是jdk1.8的
添加依赖Jsch-0.1.54.jar
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.54</version> </dependency>
FTP上传下载文件例子
1 import sun.net.ftp.FtpClient; 2 import sun.net.ftp.FtpProtocolException; 3 4 import java.io.*; 5 import java.net.InetSocketAddress; 6 import java.net.SocketAddress; 7 8 /** 9 * Java自带的API对FTP的操作 10 */ 11 public class Test { 12 private FtpClient ftpClient; 13 14 Test(){ 15 /* 16 使用默认的端口号、用户名、密码以及根目录连接FTP服务器 17 */ 18 this.connectServer("192.168.56.130", 21, "jiashubing", "123456", "/home/jiashubing/ftp/anonymous/"); 19 } 20 21 public void connectServer(String ip, int port, String user, String password, String path) { 22 try { 23 /* ******连接服务器的两种方法*******/ 24 ftpClient = FtpClient.create(); 25 try { 26 SocketAddress addr = new InetSocketAddress(ip, port); 27 ftpClient.connect(addr); 28 ftpClient.login(user, password.toCharArray()); 29 System.out.println("login success!"); 30 if (path.length() != 0) { 31 //把远程系统上的目录切换到参数path所指定的目录 32 ftpClient.changeDirectory(path); 33 } 34 } catch (FtpProtocolException e) { 35 e.printStackTrace(); 36 } 37 } catch (IOException ex) { 38 ex.printStackTrace(); 39 throw new RuntimeException(ex); 40 } 41 } 42 43 /** 44 * 关闭连接 45 */ 46 public void closeConnect() { 47 try { 48 ftpClient.close(); 49 System.out.println("disconnect success"); 50 } catch (IOException ex) { 51 System.out.println("not disconnect"); 52 ex.printStackTrace(); 53 throw new RuntimeException(ex); 54 } 55 } 56 57 /** 58 * 上传文件 59 * @param localFile 本地文件 60 * @param remoteFile 远程文件 61 */ 62 public void upload(String localFile, String remoteFile) { 63 File file_in = new File(localFile); 64 try(OutputStream os = ftpClient.putFileStream(remoteFile); 65 FileInputStream is = new FileInputStream(file_in)) { 66 byte[] bytes = new byte[1024]; 67 int c; 68 while ((c = is.read(bytes)) != -1) { 69 os.write(bytes, 0, c); 70 } 71 System.out.println("upload success"); 72 } catch (IOException ex) { 73 System.out.println("not upload"); 74 ex.printStackTrace(); 75 } catch (FtpProtocolException e) { 76 e.printStackTrace(); 77 } 78 } 79 80 /** 81 * 下载文件。获取远程机器上的文件filename,借助TelnetInputStream把该文件传送到本地。 82 * @param remoteFile 远程文件路径(服务器端) 83 * @param localFile 本地文件路径(客户端) 84 */ 85 public void download(String remoteFile, String localFile) { 86 File file_in = new File(localFile); 87 try(InputStream is = ftpClient.getFileStream(remoteFile); 88 FileOutputStream os = new FileOutputStream(file_in)){ 89 90 byte[] bytes = new byte[1024]; 91 int c; 92 while ((c = is.read(bytes)) != -1) { 93 os.write(bytes, 0, c); 94 } 95 System.out.println("download success"); 96 } catch (IOException ex) { 97 System.out.println("not download"); 98 ex.printStackTrace(); 99 }catch (FtpProtocolException e) { 100 e.printStackTrace(); 101 } 102 } 103 104 public static void main(String agrs[]) { 105 Test fu = new Test(); 106 107 //下载测试 108 String filepath[] = {"aa.xlsx","bb.xlsx"}; 109 String localfilepath[] = {"E:/lalala/aa.xlsx","E:/lalala/bb.xlsx"}; 110 for (int i = 0; i < filepath.length; i++) { 111 fu.download(filepath[i], localfilepath[i]); 112 } 113 114 //上传测试 115 String localfile = "E:/lalala/tt.xlsx"; 116 String remotefile = "tt.xlsx"; //上传 117 fu.upload(localfile, remotefile); 118 fu.closeConnect(); 119 120 } 121 122 }
SFTP上传下载文件例子
1 import com.jcraft.jsch.*; 2 3 import java.util.Properties; 4 5 /** 6 * 解释一下SFTP的整个调用过程,这个过程就是通过Ip、Port、Username、Password获取一个Session, 7 * 然后通过Session打开SFTP通道(获得SFTP Channel对象),再在建立通道(Channel)连接,最后我们就是 8 * 通过这个Channel对象来调用SFTP的各种操作方法.总是要记得,我们操作完SFTP需要手动断开Channel连接与Session连接。 9 * @author jiashubing 10 * @since 2018/5/8 11 */ 12 public class SftpCustom { 13 14 private ChannelSftp channel; 15 private Session session; 16 private String sftpPath; 17 18 SftpCustom() { 19 /* 20 使用端口号、用户名、密码以连接SFTP服务器 21 */ 22 this.connectServer("192.168.56.130", 22, "jiashubing", "123456", "/home/ftp/"); 23 } 24 25 SftpCustom(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String sftpPath) { 26 this.connectServer(ftpHost, ftpPort, ftpUserName, ftpPassword, sftpPath); 27 } 28 29 public void connectServer(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String sftpPath) { 30 try { 31 this.sftpPath = sftpPath; 32 33 // 创建JSch对象 34 JSch jsch = new JSch(); 35 // 根据用户名,主机ip,端口获取一个Session对象 36 session = jsch.getSession(ftpUserName, ftpHost, ftpPort); 37 if (ftpPassword != null) { 38 // 设置密码 39 session.setPassword(ftpPassword); 40 } 41 Properties configTemp = new Properties(); 42 configTemp.put("StrictHostKeyChecking", "no"); 43 // 为Session对象设置properties 44 session.setConfig(configTemp); 45 // 设置timeout时间 46 session.setTimeout(60000); 47 session.connect(); 48 // 通过Session建立链接 49 // 打开SFTP通道 50 channel = (ChannelSftp) session.openChannel("sftp"); 51 // 建立SFTP通道的连接 52 channel.connect(); 53 } catch (JSchException e) { 54 //throw new RuntimeException(e); 55 } 56 } 57 58 /** 59 * 断开SFTP Channel、Session连接 60 */ 61 public void closeChannel() { 62 try { 63 if (channel != null) { 64 channel.disconnect(); 65 } 66 if (session != null) { 67 session.disconnect(); 68 } 69 } catch (Exception e) { 70 // 71 } 72 } 73 74 /** 75 * 上传文件 76 * 77 * @param localFile 本地文件 78 * @param remoteFile 远程文件 79 */ 80 public void upload(String localFile, String remoteFile) { 81 try { 82 remoteFile = sftpPath + remoteFile; 83 channel.put(localFile, remoteFile, ChannelSftp.OVERWRITE); 84 channel.quit(); 85 } catch (SftpException e) { 86 //e.printStackTrace(); 87 } 88 } 89 90 /** 91 * 下载文件 92 * 93 * @param remoteFile 远程文件 94 * @param localFile 本地文件 95 */ 96 public void download(String remoteFile, String localFile) { 97 try { 98 remoteFile = sftpPath + remoteFile; 99 channel.get(remoteFile, localFile); 100 channel.quit(); 101 } catch (SftpException e) { 102 //e.printStackTrace(); 103 } 104 } 105 106 public static void main(String[] args) { 107 SftpCustom sftpCustom = new SftpCustom(); 108 //上传测试 109 String localfile = "E:/lalala/tt.xlsx"; 110 String remotefile = "/home/ftp/tt2.xlsx"; 111 sftpCustom.upload(localfile, remotefile); 112 113 //下载测试 114 sftpCustom.download(remotefile, "E:/lalala/tt3.xlsx"); 115 116 sftpCustom.closeChannel(); 117 } 118 119 }
Jsch-0.1.54.jar 学习了解
ChannelSftp类是JSch实现SFTP核心类,它包含了所有SFTP的方法,如:
文件上传put(),
文件下载get(),
进入指定目录cd().
得到指定目录下的文件列表ls().
重命名指定文件或目录rename().
删除指定文件rm(),创建目录mkdir(),删除目录rmdir().
大家引用方法时可以快速参考一下,具体传参需参考源码~
最后还要提一下的就是JSch支持的三种文件传输模式:
● APPEND 追加模式,如果目标文件已存在,传输的文件将在目标文件后追加。
● RESUME 恢复模式,如果文件已经传输一部分,这时由于网络或其他任何原因导致文件传输中断,如果下一次传输相同的文件,则会从上一次中断的地方续传。
● OVERWRITE 完全覆盖模式,这是JSch的默认文件传输模式,即如果目标文件已经存在,传输的文件将完全覆盖目标文件,产生新的文件。
FTP和SFTP区别
FTP是一种文件传输协议,一般是为了方便数据共享的。包括一个FTP服务器和多个FTP客户端。FTP客户端通过FTP协议在服务器上下载资源。而SFTP协议是在FTP的基础上对数据进行加密,使得传输的数据相对来说更安全。但是这种安全是以牺牲效率为代价的,也就是说SFTP的传输效率比FTP要低(不过现实使用当中,没有发现多大差别)。个人肤浅的认为就是:一;FTP要安装,SFTP不要安装。二;SFTP更安全,但更安全带来副作用就是的效率比FTP要低些。
建议使用sftp代替ftp。
主要因为:
1、可以不用额外安装任何服务器端程序
2、会更省系统资源。
3、SFTP使用加密传输认证信息和传输数据,相对来说会更安全。
4、也不需要单独配置,对新手来说比较简单(开启SSH默认就开启了SFTP)。
参考
[1].https://blog.csdn.net/g5628907/article/details/78281864
[2].https://www.cnblogs.com/xuliangxing/p/7120130.html
[3].https://jingyan.baidu.com/article/6079ad0e7feae028ff86dbf9.html
以上是关于java连接Sftp服务器后,使用第三方jar com.jcraft.jsch.ChannelSftp;用get()方法获取的InputStream流为空的主要内容,如果未能解决你的问题,请参考以下文章