Java中java.io包为我们提供了输入流和输出流,对文件的读写基本上都依赖于这些封装好的关于流的类中来实现。前段时间遇到了以下两种需求:
1、与某系统对接,每天获取最新的图片并显示在前端页面。该系统提供的是一个http协议的图片URL,本来获取到该系统的图片地址以后在HTML中显示就可以了,但是该系统不太稳定,图片URL经常不能使用,而且每天生成图片不一定成功,
对自己系统的功能影响很大,emm。。。所以就考虑每天从该系统下载最新的图片到本地更新保存,没有新图片就继续使用上次的图片。
2、公司算法团队的同事完成了一个视频分析的检测功能,会生成一些截取的短视频文件,系统需要获取并保存这些视频文件。算法运行在Linux系统,没有搭建FTP服务器,所以就需要系统从运行算法的Linux系统复制文件到系统本地保存起来。
这两个需求实现起来都是大同小异,思路就是读取文件然后写到指定路径,只不过http协议的图片地址可以直接读取然后保存,而Linux系统的文件需要远程连接到该服务器然后再下载文件,这就需要我们引入以下依赖:
<!--远程读取服务器文件--> <dependency> <groupId>ch.ethz.ganymed</groupId> <artifactId>ganymed-ssh2</artifactId> <version>262</version> </dependency> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.4</version> </dependency>
废话不说了,先上代码:
package com.XXX.utils; import ch.ethz.ssh2.*; import com.databus.Log; import com.mysql.jdbc.StringUtils; import java.io.*; import java.net.*; public class FileUtils { public static boolean downloadFile(String urlString,String fileName,String filePath) { boolean bool = false; InputStream is = null; FileOutputStream os = null; try { Log.info("文件路径:" + urlString); // 构造URL java.net.URL url = new java.net.URL(urlString); // 打开连接 URLConnection con = url.openConnection(); // 输入流 is = con.getInputStream(); // 1K的数据缓冲 byte[] bs = new byte[1024]; // 读取到的数据长度 int len; //判断指定目录是否存在,不存在则先创建目录 File file = new File(filePath); if (!file.exists()) file.mkdirs(); //fileName如果不包含文件后缀,则需要加上后缀,如:fileName + ".jpg";fileName + ".txt"; os = new FileOutputStream(filePath + fileName, false);//false:覆盖文件,true:在原有文件后追加 // 开始读取 while ((len = is.read(bs)) != -1) { os.write(bs, 0, len); } bool = true; Log.info("文件保存成功:" + fileName); }catch (Exception e){ e.printStackTrace(); }finally { // 完毕,关闭所有链接 if (null != os){ try { os.flush(); os.close(); }catch (IOException e){ e.printStackTrace(); } } if (null != is){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return bool; } //远程下载服务器文件 public static boolean copyFile(String ip,int port,String userName,String password,String sourceFile,String targetFile,String targetFileName){ boolean bool = false; Connection conn = null; Session session = null; try { if (StringUtils.isNullOrEmpty(ip) || StringUtils.isNullOrEmpty(userName) || StringUtils.isNullOrEmpty(password) || StringUtils.isNullOrEmpty(sourceFile) || StringUtils.isNullOrEmpty(targetFile)){ return bool; } conn = new Connection(ip,port); conn.connect(); boolean isAuth = conn.authenticateWithPassword(userName,password); if (!isAuth){ Log.info("算法主机连接失败"); return bool; } //执行命令 session = conn.openSession(); //执行命令并打印执行结果 session.execCommand("df -h"); InputStream staout = new StreamGobbler(session.getStdout()); BufferedReader br = new BufferedReader(new InputStreamReader(staout)); String line = null; while ((line = br.readLine()) != null){ System.out.println(line); } br.close(); //下载文件到本地 SCPClient scpClient = conn.createSCPClient(); SCPInputStream scpis = scpClient.get(sourceFile); //判断指定目录是否存在,不存在则先创建目录 File file = new File(targetFile); if (!file.exists()) file.mkdirs(); FileOutputStream fos = new FileOutputStream(targetFile + targetFileName); byte[] buffer = new byte[1024]; int len = 0; while ((len = scpis.read(buffer)) != -1){ fos.write(buffer,0,len); } fos.close(); bool = true; //SFTP /*SFTPv3Client sftPClient = new SFTPv3Client(conn); sftPClient.createFile(""); sftPClient.close();*/ }catch (Exception e){ e.printStackTrace(); Log.info(e.getMessage()); Log.info("保存失败:" + sourceFile); }finally { if (null != session){ session.close(); } if (null != conn) { conn.close(); } } return bool; } }
第一个方法downloadFile(String urlString,String fileName,String filePath)与我们读写文件没什么区别,我们主要说一下远程读取Linux服务器文件的方法:
copyFile(String ip,int port,String userName,String password,String sourceFile,String targetFile,String targetFileName)
可以看到,我们需要Linux服务器的ip、ssh开放的端口号(一般默认是22)、服务器用户名和密码,所以我们要确保Linux服务器已经开放ssh连接,否则我们的程序根本就连不上服务器,更不要说复制文件了。
其实ssh2连接远程服务器,就和我们用Xshell连接服务器是一样的,不但可以复制文件,也可以执行Linux命令对Linux进行操作,看上面的一段代码:
//执行命令 session = conn.openSession(); //执行命令并打印执行结果 session.execCommand("df -h"); InputStream staout = new StreamGobbler(session.getStdout()); BufferedReader br = new BufferedReader(new InputStreamReader(staout)); String line = null; while ((line = br.readLine()) != null){ System.out.println(line); } br.close();
这段代码与复制文件没有关系,之所以保留就是要说明一下,我们执行了df -h 命令(查询服务器磁盘使用情况),将会得到磁盘的具体使用情况,与下图效果相同。所以我们可以用ssh2做很多事情,有兴趣的童鞋可以多了解。
另外在copyFile()方法的最后有一段注释的代码:
//SFTP /*SFTPv3Client sftPClient = new SFTPv3Client(conn); sftPClient.createFile("files"); sftPClient.close();*/
我们也可以通过建立SFTP连接来远程操作目录和文件,比如:创建、删除目录,创建、删除文件等。
关于ssh2包的其他功能和用法不再引申,有兴趣的童鞋欢迎在评论区交流。
以上就是Java下载远程服务器文件到本地(基于http协议和ssh2协议)的详细内容,更多关于java 下载服务器文件的资料请关注小牛知识库其它相关文章!
Http 协议基本使用 在 SOFARPC (非SOFABoot 环境)中,当使用Http作为服务端协议的时候,支持Json作为序列化方式,作为一些基础的测试方式使用。 SOFARPC API 使用 发布服务 // 只有1个线程 执行 ServerConfig serverConfig = new ServerConfig() .setStopTimeout(60000) .setPort(12
HTTP (HyperText Transfer Protocol, 超文本传输协议)是互联网上应用最为广泛的一种网络协议,它是基于 TCP 的应用层协议,简单地说就是客户端和服务器进行通信的一种规则,它的模式非常简单,就是客户端发起请求,服务器响应请求。 HTTP 最早于 1991 年发布,是 0.9 版,不过目前该版本已不再用。HTTP 目前在使用的版本主要有: HTTP/1.0,于 1996
名为charles的工具中有一个功能,允许您映射远程请求: http://www.charlesproxy.com/documentation/tools/map-remote/ 基本上,它可以将任何请求发送到服务器(即使不是运行它的人),然后向另一台服务器发出新请求,保留路径和查询字符串。然后,来自第二台服务器的响应将覆盖来自第一台服务器的响应。 我只是想知道是否有一个节点模块可以做到这一点。我
主要内容:1. HTTP协议,2. 基本功能,3. 架构,4. Http协议详细信息理解协议对于掌握安全测试非常重要。当我们拦截网络服务器和客户端之间的数据包数据时,您将能够理解协议的重要性。 1. HTTP协议 超文本传输协议(HTTP)是用于分布式协作超媒体信息系统的应用程序级协议。它是自1990年以来万维网数据通信的基础。HTTP是一种通用的无状态协议,可以用于其他目的,也可以使用其请求方法,错误代码和标头的扩展。 基本上,HTTP是基于TCP/IP的通信协议,用于通过We
本服务条款(以下简称“本协议”)由北京百度网讯科技有限公司(以下简称“百度”)与您(以下简称“您”或“用户”)订立,用于规范您对百度统计(以下简称“本服务”)的使用。只要您点击 “确定”按钮、完成注册程序或开通、使用本服务,即代表您已理解并同意本协议,特别是以黑体字标示出的关于百度统计及您重大权益的条款均以知晓、理解并接受,同意将其作为确定双方权利义务的依据。如果您不同意本协议,请您立即停止使用本
京东小程序开放平台开发者服务协议 【请认真阅读并理解以下内容,其中以加粗方式显著标识的文字,请着重阅读、慎重考虑】 前言 1、本协议由拟在京东小程序开放平台(以下或简称“京东小程序平台”或“小程序平台”)开发京东小程序(以下或简称“小程序”)的京东小程序开发者(以下简称“开发者”,“乙方”或“您”)与京东小程序开放平台运营方(以下或简称“京东”或“甲方”)共同缔结,具有合同效力。 2、本协议由协议