利用sftp進行上傳、單個下載、批量下載和刪除
最近公司讓用SFTP用來和遠端進行互動,學習了;一段時間sftp,現在將程式碼乾貨獻上,希望對大家能夠有所幫助:
1. 在src/com/zkr/sftp(建議建立在src下)下建立sftp.properties檔案:
sftp.host=127.0.0.1
sftp.port=22
sftp.username=zhen
sftp.password=12345
sftp.timeout=60000
sftp.privateKey
sftp.passphrase
2. 建立SFTPUtils類,完成上傳、下載、刪除功能:
package com.zkr.sftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream.GetField;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import com.enterprisedt.util.debug.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
public class SftpUtils {
private static final Logger log = Logger.getLogger(SftpUtils.class); // 用來記錄日誌
Session session = null;
String privateKey = null;
String passphrase = null;
String host = null; // sftp伺服器的IP
String username = null; // 使用者名稱
String password = null; // 密碼
int timeout = 60000; // 超時時間
int port = 22; // 埠號
/**
* 在建構函式中讀取配置檔案
*/
public SftpUtils() {
File file = new File("src/com/zkr/sftp/sftp.properties");
InputStream in = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e) {
log.error("異常:檔案沒有找到", e);
}
Properties prop = new Properties();
try {
prop.load(in);
} catch (IOException e) {
log.error("異常:載入配置檔案失敗", e);
}
// 讀取配置檔案資訊
host = prop.getProperty("sftp.host");
port = Integer.parseInt(prop.getProperty("sftp.port"));
username = prop.getProperty("sftp.username");
password = prop.getProperty("sftp.password");
timeout = Integer.parseInt(prop.getProperty("sftp.timeout"));
privateKey = prop.getProperty("sftp.privateKey");
passphrase = prop.getProperty("sftp.passphrase");
log.info("try to connect to " + host + ",username:" + username
+ ",password:" + password + ",port:" + port);
}
/**
* 得到連線
*
* @return
*/
private ChannelSftp GetConnectSftp() {
JSch jsch = new JSch();
ChannelSftp channelSftp = null;
try {
if (privateKey != null && !"".equals(privateKey)) {
// 使用金鑰驗證方式,金鑰可以使有口令的金鑰,也可以是沒有口令的金鑰
if (passphrase != null && "".equals(passphrase)) {
jsch.addIdentity(privateKey, passphrase);
} else {
jsch.addIdentity(privateKey);
}
}
session = jsch.getSession(username, host, port);
// 設定密碼
if (password != null && !"".equals(password)) {
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");// do not verify host
// 為session物件設定properties
session.setConfig(config);
// 設定超時
session.setTimeout(timeout);
//session.setServerAliveInterval(92000);
session.connect();
// 引數sftp指明要開啟的連線是sftp連線
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
System.out.println("連線成功");
} catch (JSchException e) {
// log.error("異常:連線失敗",e);
System.out.println("連線失敗");
}
return channelSftp;
}
/**
* 下載
*
* @param directory
* 原始檔在伺服器的路徑,不包括檔名
* @param srcFilename
* 原始檔名
* @param dstPath
* 下載到本地的目標路徑
*/
public void download(String directory, String srcFilename, String dstPath) {
ChannelSftp channelSftp = null;
// 得到連線
channelSftp = GetConnectSftp();
try {
if (channelSftp != null) {
// 進入伺服器相應路徑
channelSftp.cd(directory);
// 進行下載
channelSftp.get(srcFilename, dstPath);
log.info("下載成功:" + srcFilename);
}
} catch (SftpException e) {
log.error("異常:下載失敗:" + srcFilename, e);
e.printStackTrace();
} finally {
// 釋放連線
disconnected(channelSftp);
}
}
/**
* 下載 為批量下載做準備
*
* @param directory 原始檔在伺服器的路徑,不包括檔名
* @param srcFilename 原始檔名
* @param dstPath 下載到本地的目標路徑
* @param channelSftp
*/
private void download(String directory, String srcFilename, String dstPath,
ChannelSftp channelSftp) {
try {
if (channelSftp != null) {
channelSftp.cd(directory);
channelSftp.get(srcFilename, dstPath);
}
} catch (SftpException e) {
log.error("異常: 下載失敗:" + directory + "/" + srcFilename, e);
e.printStackTrace();
}
}
/**
* 批量下載
* @param pathName 伺服器端目錄
* @param dstPath 本地目錄
*/
public void batchDownload(String pathName, String dstPath) {
ChannelSftp channelSftp = null;
// 得到連線
channelSftp = GetConnectSftp();
//批量下載管理
batchDownMag(pathName, dstPath, channelSftp);
//斷開連線
disconnected(channelSftp);
}
/**
* 上傳
*
* @param directory
* 上傳目錄,不包括檔名
* @param srcPath
* 本地檔案路徑,包括檔名
* @param dstFilename
* 在伺服器中對上傳檔案進行命名
*/
public void upload(String directory, String srcPath, String dstFilename) {
ChannelSftp channelSftp = null;
// 獲取連線
channelSftp = GetConnectSftp();
if (channelSftp != null) {
// 若存在directory這個目錄,則進入其中;若不存在,則先在伺服器先建立該目錄並進入
createDir(directory, channelSftp);
try {
channelSftp.put(srcPath, dstFilename);
log.info("上傳成功:" + directory);
} catch (SftpException e) {
log.error("異常:上傳失敗:" + directory, e);
e.printStackTrace();
} finally {
// 釋放連線
disconnected(channelSftp);
}
}
}
/**
* 刪除檔案
*
* @param directory
* 要刪除檔案所在目錄,不包括檔名
* @param deleteFilename
* 要刪除的檔名
*/
public void delete(String directory, String deleteFilename) {
ChannelSftp channelSftp = null;
// 獲取連線
channelSftp = GetConnectSftp();
if (channelSftp != null) {
try {
// 進入伺服器相應目錄
channelSftp.cd(directory);
// 刪除檔案
channelSftp.rm(deleteFilename);
} catch (SftpException e) {
log.error("異常:刪除失敗:" + deleteFilename, e);
e.printStackTrace();
} finally {
// 釋放連線
disconnected(channelSftp);
}
}
}
/**
* 開啟或進入目錄
*
* @param directory
* @param channelsftp
* @return
*/
private boolean openDir(String directory, ChannelSftp channelsftp) {
try {
channelsftp.cd(directory);
return true;
} catch (SftpException e) {
log.error("異常: 該目錄不存在:" + directory, e);
// e.printStackTrace();
return false;
}
}
/**
* 批量下載管理
*
* @param pathName
* 伺服器端地址
* @param dstPath
* 本地地址
* @param channelSftp
*/
private void batchDownMag(String pathName, String dstPath,
ChannelSftp channelSftp) {
// 確保服務端地址是絕對地址
if (!pathName.startsWith("/")) {
pathName = "/" + pathName;
}
// 目錄標誌符,若為有效地址,則為true,否則為false
boolean flag = openDir(pathName, channelSftp);
if (flag) {
try {
Vector vv = channelSftp.ls(pathName);
if (vv == null && vv.size() == 0) {
return;
} else {
// 遍歷當前目錄所有檔案及子資料夾
for (Object object : vv) {
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object;
// 得到當前項的名稱(可能是檔名,也可能是資料夾名)
String filename = entry.getFilename();
// 去除無關項
if (".".equals(filename) || "..".equals(filename)) {
continue;
}
if (openDir(pathName + "/" + filename, channelSftp)) {
// 能開啟,說明是目錄,接著遍歷
String dstPathChild = dstPath + "/" + filename;
File file = new File(dstPathChild);
//若本地不存在該目錄,則進行建立
if (!file.isDirectory()) {
file.mkdirs();
}
//進行遞迴
batchDownMag(pathName + "/" + filename,
dstPathChild, channelSftp);
} else {
download(pathName, filename, dstPath, channelSftp);
}
}
}
} catch (SftpException e) {
log.error("遍歷目錄失敗:" + pathName, e);
}
} else {
log.info("對應的目錄" + pathName + "不存在!");
}
}
/**
* 斷開連線
*
* @param channelSftp
*/
private void disconnected(ChannelSftp channelSftp) {
if (channelSftp != null) {
try {
// 判斷session是否連線
if (channelSftp.getSession().isConnected()) {
// 若連線,則釋放連線
channelSftp.getSession().disconnect();
}
} catch (JSchException e) {
log.error("異常:無法獲取session", e);
e.printStackTrace();
}
// 判斷channelSftp是否連線
if (channelSftp.isConnected()) {
// 若連線,則釋放連線
channelSftp.disconnect();
}
}
}
/**
* 若存在相應目錄,則進入該目錄中 若不存在相應目錄,則會在伺服器中建立並進入該目錄中
*
* @param directory
* @param channelSftp
*/
private void createDir(String directory, ChannelSftp channelSftp) {
try {
// 判斷是否存在相應目錄
if (isDirExist(directory, channelSftp)) {
// 若存在,則進入並設定為當前目錄
channelSftp.cd(directory);
return;
}
// 對路徑進行拆分
String[] pathArray = directory.split("/");
// 加"/"設定為絕對路徑
StringBuffer filePath = new StringBuffer("/");
for (String path : pathArray) {
// 若directory為絕對路徑,則為true
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
if (isDirExist(filePath.toString(), channelSftp)) {
channelSftp.cd(filePath.toString());
} else {
// 建立目錄
channelSftp.mkdir(filePath.toString());
// 進入並設定為當前路徑
channelSftp.cd(filePath.toString());
}
}
} catch (SftpException e) {
log.error("異常:建立路徑錯誤:" + directory, e);
e.printStackTrace();
}
}
/**
* 判斷目錄是否存在
*
* @param directory
* @param channelSfrp
* @return
*/
private boolean isDirExist(String directory, ChannelSftp channelSftp) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = channelSftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (SftpException e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
e.printStackTrace();
}
return isDirExistFlag;
}
}
3.寫測試類進行測試
package com.zkr.sftp;
import com.jcraft.jsch.ChannelSftp;
public class Demo {
@Test
public void test1() throws Exception {
SftpUtils sftputils = new SftpUtils();
String directory = "sdf/史蒂夫";
String srcPath = "E:/111/花好月不圓/若只如初見.txt";
String dstFilename = "情深卻只增悲痛.txt";
String srcFilename = "秋風何時悲畫卷.xlsx";
String dstPath = "E:/111/zhen";
String deleteFilename = "[www.java1234.com]redis設計與實現(第二版).pdf";
//將本地中的E:/111/花好月不圓/若只如初見.txt上傳到sftp伺服器中的sdf/史蒂夫的目錄中,並起名為情深卻只增悲痛.txt
sftputils.upload(directory, srcPath, dstFilename);
//將sftp伺服器中的sdf/史蒂夫/秋風何時悲畫卷.xlsx下載到本地的E:/111/zhen目錄中
sftputils.download(directory, srcFilename, dstPath);
//刪除sftp伺服器中的sdf/史蒂夫/[www.java1234.com]redis設計與實現(第二版).pdf
sftputils.delete(directory, deleteFilename);
}
//測試批量下載功能
@Test
public void test2(){
SftpUtils sftpUtils=new SftpUtils();
String pathName="/sdf/11/史蒂夫";
String dstPath="E:/33";
sftpUtils.batchDownload(pathName, dstPath);
}
}