需求:实现文件的上传和下载,对安全性有较高的要求。
在ftp与sftp中选择sftp,SFTP是Secure File Transfer Protocol的缩写,安全文件传送协议,可以为文件提供一种安全的加密方法。跟ftp的语法功能几乎一模一样。sftp传输方式采用了加密/解密技术,故效率要比ftp低很多,当对安全性要求更高的时候,代替ftp使用
使用秘钥方式建立连接,秘钥配置如下:
假设服务器的地址是192.168.136.132,登录该服务器的用户名是root。
1、在本机中生成秘钥,SSH有专门创建SSH密钥的工具ssh-keygen,命令如下:
ssh-keygen -t rsa
会在当前用户下文件夹下生成一个.ssh隐藏文件夹。
如果是Windows用户的话,可以使用git bash执行该命令行,同样会在c盘的用户目录下生成一个.ssh隐藏文件夹。
2、将公钥传给服务器(就是你要下载文件的机器),命令如下:
ssh-copy-id root@192.168.136.132
秘钥配置完毕。
创建工具类SFTPUtil:
静态变量:
private static Logger logger = LoggerFactory.getLogger(SFTPUtil.class);
private static Session session = null;
private static ChannelSftp channel = null;
private static int ftpPort = 22;
private static String PROP = "cfg.properties";
获取SFTP通道:
public static ChannelSftp getConnect(){
FileInputStream is;
try {
is = new FileInputStream(PROP);
} catch (FileNotFoundException e) {
logger.info("找不到配置文件(cfg.properties).",e);
return null;
}
Properties prop = new Properties();
try {
prop.load(is);
GlobalProperties.setGlobalProp(prop);
} catch (IOException e) {
logger.info("加载配置文件失败.",e);
return null;
}
String ftpHost = prop.getProperty("downloadHost");
String port = prop.getProperty("downloadftpPort");
String ftpUserName = prop.getProperty("downloadUserName");
String priKeyBasePath = prop.getProperty("priBaseKeyPath");
if(port != null && !port.equals("")){
ftpPort = Integer.parseInt(port);
}
JSch jsch = new JSch();
try{
jsch.addIdentity(priKeyBasePath);
session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
logger.debug("session created.");
String ftpTO=prop.getProperty("downloadtimeout");
if (!(ftpTO==null||"".equals(ftpTO))) {
int ftpTimeout=Integer.parseInt(ftpTO);
session.setTimeout(ftpTimeout);
}
session.setConfig("StrictHostKeyChecking", "no");
session.setConfig("UseDNS", "no");
session.connect(); // 经由过程Session建树链接
logger.debug("Opening SFTP Channel.");
channel = (ChannelSftp) session.openChannel("sftp"); // 打开SFTP通道
channel.connect(); // 建立SFTP通道的连接
}catch (JSchException e) {
logger.error("sftp getConnect error : "+e);
}
return channel;
}
关闭通道:
public static void closeChannel() throws Exception {
try {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
} catch (Exception e) {
logger.error("close sftp error", e);
throw new Exception( "close ftp error.");
}
}
上传文件:
public static void uploadFile(String localFile, String newName, String remoteFoldPath) throws Exception{
InputStream input = null;
try {
input = new FileInputStream(new File(localFile));
// 改变当前路径到指定路径
channel.cd(remoteFoldPath);
channel.put(input, newName);
} catch (Exception e) {
logger.error("Upload file error", e);
throw new Exception( "Upload file error.");
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
throw new Exception("Close stream error.");
}
}
}
}
下载文件:
public void downloadFile(String remoteFile, String remotePath, String localFile) throws Exception {
OutputStream output = null;
File file = null;
try {
file = new File(localFile);
if (!checkFileExist(localFile)) {
file.createNewFile();
}
output = new FileOutputStream(file);
channel.cd(remotePath);
channel.get(remoteFile, output);
} catch (Exception e) {
logger.error("Download file error", e);
throw new Exception("Download file error.");
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
throw new Exception("Close stream error.");
}
}
}
}
private boolean checkFileExist(String localPath) {
File file = new File(localPath);
return file.exists();
}
public Vector listFiles(String remotePath) throws Exception {
Vector vector = null;
try {
vector = channel.ls(remotePath);
} catch (SftpException e) {
logger.error("List file error", e);
throw new Exception("list file error.");
}
return vector;
}