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协议)的更多相关文章

  1. java远程下载文件到本地

    方法一 ** * 下载远程文件并保存到本地 * * @param remoteFilePath-远程文件路径 * @param localFilePath-本地文件路径(带文件名) */ public ...

  2. PHP实现远程下载文件到本地

    PHP实现远程下载文件到本地 投稿:hebedich 字体:[增加 减小] 类型:转载   经常写采集器发布接口需要使用到远程附件的功能,所以自己写了一个PHP远程下载文件到本地的函数,一般情况下已经 ...

  3. PHP CURL实现远程下载文件到本地

    <?php //$result=httpcopy('http://www.phpernote.com/image/logo.gif'); echo '<pre>';print_r($ ...

  4. java实现下载文件到本地

    代码如下: URL url = new URL("http://www.cnblogs.com/images/logo_small.gif"); URLConnection con ...

  5. 使用xshell从远程服务器下载文件到本地

    XSHELL工具上传文件到Linux以及下载文件到本地(Windows) Xshell很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz.首先你的L ...

  6. 在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹)

    在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹) 1 列出所有需要copy的sh文件 -bash-4.1$ ll /mysqllog/osw/*.sh ...

  7. C#使用WebClient下载文件到本地目录

    C#使用WebClient下载文件到本地目录. 1.配置本地目录路径 <appSettings> <!--文件下载目录--> <add key="Downloa ...

  8. Js点击按钮下载文件到本地(兼容多浏览器)

    实现点击 用纯 js(非jquery)  下载文件到本地 自己尝试,加网上找了好久未果,如: window.open(url)   location.href=url   form表单提交   ifr ...

  9. 【转】XSHELL下直接下载文件到本地(Windows)

    XSHELL下直接下载文件到本地(Windows) http://www.cnblogs.com/davytitan/p/3966606.html

随机推荐

  1. 学习笔记:斜率优化DP

    作为数学渣,先复习一下已知两点\((x_1, y_1)\), \((x_2, y_2)\),怎么求过两点的一次函数的斜率... 待定系数法代入 \(y = kx + b\) 有: \(x_1k + b ...

  2. 题解-MtOI2019 幽灵乐团

    题面 MtOI2019 幽灵乐团 给定 \(p\),\(Cnt\) 组测试数据,每次给 \(a,b,c\),求 \[\prod_{i=1}^a\prod_{j=1}^b\prod_{k=1}^c\le ...

  3. 关于微信NFC功能开发的链接总结

    特此申明:若有侵权,请联系我,我会第一时间删除 一. 小程序开发一般流程: 首先调用 wx.getHCEState(OBJECT), 判断设备是否支持NFC,(ios,android兼容性处理) 调用 ...

  4. MySQL技术内幕InnoDB存储引擎(四)——表相关

    表是什么? 就是关于特定实体地数据集合,是关系型数据库模型地核心. 索引组织表 什么是索引组织表? 表中数据都是根据主键的顺序组织存放的,这种存储方式就是索引组织表.就是存储在一个索引结构中的表. 也 ...

  5. linux 设置别名

    [root@oldboyedu45-xy data]# alias(查找别名) alias cp='cp -i' alias l.='ls -d .* --color=auto' alias ll=' ...

  6. 从0到1实战移动Web App开发

    从0到1实战移动Web App开发   教程介绍 从0到1 实战webapp,通过热门的web前端技术实现移动端app应用,先基础.后实战,在讲解的同时引导思考,会抛出自己独特的观点,一行一行写代码讲 ...

  7. 安卓和ios的app证书过期的相关问题汇总

    一,ios的APP的发布流程请见:ios的APP的发布流程 http://www.jianshu.com/p/b1b77d804254 这篇文章写得很好很全面 二,app证书过期了怎么办: IOS的情 ...

  8. 1款开源工具,实现自动化升级K3S集群!

    即便你的集群能够平稳运行,Kubernetes升级依旧是一项艰难的任务.由于每3个月Kubernetes会发布一个新版本,所以升级是十分必要的.如果一年内你不升级你的Kubernetes集群,你就会落 ...

  9. pytorch实现 | Deformable Convolutional Networks | CVPR | 2017

    文章转载自微信公众号:[机器学习炼丹术],请支持原创. 这一篇文章,来讲解一下可变卷积的代码实现逻辑和可视化效果.全部基于python,没有C++.大部分代码来自:https://github.com ...

  10. C# 数据结构与算法 操作系统原理 计算机网络原理 数据库开发学习

    https://www.cnblogs.com/edisonchou/p/3843287.html PDF https://files.cnblogs.com/files/netlock/%E6%95 ...