Java远程下载文件到本地(http协议和ssh2协议)
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 { /*
* 根据http路径下载文件保存到指定路径
* urlString:文件路径
* fileName:保存到本地的文件名称
* filePath:本地要保存的指定路径
* */
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 d 命令(查询服务器磁盘使用情况),将会得到磁盘的具体使用情况,与下图效果相同。所以我们可以用ssh2做很多事情,有兴趣的童鞋可以多了解。

另外在copyFile()方法的最后有一段注释的代码:
//SFTP
/*SFTPv3Client sftPClient = new SFTPv3Client(conn);
sftPClient.createFile("files");
sftPClient.close();*/
我们也可以通过建立SFTP连接来远程操作目录和文件,比如:创建、删除目录,创建、删除文件等。
关于ssh2包的其他功能和用法不再引申,有兴趣的童鞋欢迎在评论区交流。
Java远程下载文件到本地(http协议和ssh2协议)的更多相关文章
- java远程下载文件到本地
方法一 ** * 下载远程文件并保存到本地 * * @param remoteFilePath-远程文件路径 * @param localFilePath-本地文件路径(带文件名) */ public ...
- PHP实现远程下载文件到本地
PHP实现远程下载文件到本地 投稿:hebedich 字体:[增加 减小] 类型:转载 经常写采集器发布接口需要使用到远程附件的功能,所以自己写了一个PHP远程下载文件到本地的函数,一般情况下已经 ...
- PHP CURL实现远程下载文件到本地
<?php //$result=httpcopy('http://www.phpernote.com/image/logo.gif'); echo '<pre>';print_r($ ...
- java实现下载文件到本地
代码如下: URL url = new URL("http://www.cnblogs.com/images/logo_small.gif"); URLConnection con ...
- 使用xshell从远程服务器下载文件到本地
XSHELL工具上传文件到Linux以及下载文件到本地(Windows) Xshell很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz.首先你的L ...
- 在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹)
在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹) 1 列出所有需要copy的sh文件 -bash-4.1$ ll /mysqllog/osw/*.sh ...
- C#使用WebClient下载文件到本地目录
C#使用WebClient下载文件到本地目录. 1.配置本地目录路径 <appSettings> <!--文件下载目录--> <add key="Downloa ...
- Js点击按钮下载文件到本地(兼容多浏览器)
实现点击 用纯 js(非jquery) 下载文件到本地 自己尝试,加网上找了好久未果,如: window.open(url) location.href=url form表单提交 ifr ...
- 【转】XSHELL下直接下载文件到本地(Windows)
XSHELL下直接下载文件到本地(Windows) http://www.cnblogs.com/davytitan/p/3966606.html
随机推荐
- UOJ61. 【UR #5】怎样更有力气
题目链接 Statement 给定一棵 \(n\) 点树 \(T\) 和 \(m\) 个操作 v u w : 在 \(T\) 中 \(u,v\) 的最短路上所有点里面选出若干对(可以不选,可以重复), ...
- Codeforces Edu Round 65 A-E
A. Telephone Number 跟之前有一道必胜策略是一样的,\(n - 10\)位之前的数存在\(8\)即可. #include <iostream> #include < ...
- Vue-组件传值:子传父和兄弟组件间常见的传值方式
前言 上篇介绍了我对vue组件化的理解和父组件对子组件传值的方式,这篇介绍下常见的子传父和兄弟组件间的传值方式 目录 子组件向父组件传值 任意组件间的传值方式 正文 子组件向父组件传值 关键知识点:$ ...
- idea 最好用的插件
1.lombok 不用写get,set方法 2.MyBatisCodeHelperPro 3.Rainbow Brackets 彩虹括号 5.activate-power-mode 动感打字 7.Ba ...
- RabbitMQException com.rabbitmq.client.ShutdownSignalException: connection error; protocol meth
异常1 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ...
- 6 个例子教你重构 Python 代码
1. 合并嵌套的 if 条件 太多的嵌套会使代码难以理解,这在 Python 中尤为如此,因为 Python 没有括号来帮助区隔不同的嵌套级别. 阅读深度嵌套的代码容易让人烦躁,因为你必须理清哪些条件 ...
- .NET Core 使用MediatR CQRS模式 读写分离
前言 CQRS(Command Query Responsibility Segregation)命令查询职责分离模式,它主要从我们业务系统中进行分离出我们(Command 增.删.改)和(Query ...
- C# 多态virtual标记重写 以及EF6 查询性能AsNoTracking
首先你如果不用baivirtual重写的话,系统默认会为du你加new关键字,他zhi的作用是覆盖,而virtual的关键作用在dao于实现多态 virtual 代表在继承了这个类的子类里面可以使用o ...
- 个人MySQL的事务特性原理学习笔记总结
目录 个人MySQL的事务特性原理笔记总结 一.基础概念 2. 事务控制语句 3. 事务特性 二.原子性 1. 原子性定义 2. 实现 三.持久性 1. 定义 2. 实现 3. redo log存在的 ...
- 记一次Apache的代码导致生产服务耗时增加
引言 二狗:二胖快醒醒,赶紧看看刚才报警邮件,你上次写的保存用户接口耗时(<二胖的参数校验坎坷之路>)大大上升,赶紧排查下原因. 二胖:好的,马上看,内心戏可十足(心里却在抱怨,大中午的搅 ...