幸好 Apache Commons VFS 替我們實作了 SFTP 的操作,Apache Commons VFS 配合 JSch 使我們可以很簡單地使用 SSH 連接 Server 和上載檔案,下載檔案等等操作。
廢話不多說,首先要準備 3 個 Library:
- Apache Commons VFS - http://commons.apache.org/vfs/download_vfs.cgi
- Apache Commons Logging - http://commons.apache.org/logging/download_logging.cgi
- JSch - http://www.jcraft.com/jsch/
下載好後將 .jar 加到 class path 令程式找到這些 Library。
再來就是寫程式,為了方便好看,我會將所有程式碼放到 Main class 內。
第一步是製作一個 Function 去將 Protocol,Host Name,Username,Password 和 Server 上的檔案位置連接起來 (Factory Method)。令到 Apache Commons VFS 能讀得懂。
public static String createConnectionString(String hostName,
String username, String password, String remoteFilePath) {
// result: "sftp://user:[email protected]/resume.pdf
return "sftp://" + username + ":" + password + "@" + hostName + "/"
+ remoteFilePath;
}
第二步是製作一個 Function 去製造出一個 SFTP 預設的設定 (Factory Method):
public static FileSystemOptions createDefaultOptions()
throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
第三步是製作一個上載檔案的 Function:
public static void upload(String hostName, String username,
String password, String localFilePath, String remoteFilePath) {
File f = new File(localFilePath);
if (!f.exists())
throw new RuntimeException("Error. Local file not found");
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create local file object
FileObject localFile = manager.resolveFile(f.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
在這裡可以測試一下上載檔案的 Function 是否沒有問題:
/*
* args[0]: hostName
* args[1]: username
* args[2]: password
* args[3]:localFilePath
* args[4]: remoteFilePath
*/
public static void main(String[] args) {
if (args.length < 5)
throw new RuntimeException(
"Error. Please enter "
+ "args[0]: hostName, args[1]: username, args[2]: password, "
+ "args[3]: localFilePath, args[4]: remoteFilePath.");
upload(args[0], args[1], args[2], args[3], args[4]);
}
成功後 Console 會打印出 File upload success。
再來是加下載檔案的 Function:
public static void download(String hostName, String username,
String password, String localFilePath, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
String downloadFilePath = localFilePath.substring(0,
localFilePath.lastIndexOf("."))
+ "_downlaod_from_sftp"
+ localFilePath.substring(localFilePath.lastIndexOf("."),
localFilePath.length());
// Create local file object
FileObject localFile = manager.resolveFile(downloadFilePath);
// Create remote file object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
System.out.println("File download success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
測試檔案是否存在的 Function:
public static boolean exist(String hostName, String username,
String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
System.out.println("File exist: " + remoteFile.exists());
return remoteFile.exists();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
刪除 Server 檔案的 Function:
public static void delete(String hostName, String username,
String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.delete();
System.out.println("Delete remote file success");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
完整的程式:
package sftp.sample;
import java.io.File;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.impl.StandardFileSystemManager;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
public class Main {
/*
* args[0]: hostName
* args[1]: username
* args[2]: password
* args[3]: localFilePath
* args[4]: remoteFilePath
*/
public static void main(String[] args) {
if (args.length < 5)
throw new RuntimeException(
"Error. Please enter "
+ "args[0]: hostName, args[1]: username, args[2]: password, "
+ "args[3]: localFilePath, args[4]: remoteFilePath.");
upload(args[0], args[1], args[2], args[3], args[4]);
exist(args[0], args[1], args[2], args[4]);
download(args[0], args[1], args[2], args[3], args[4]);
delete(args[0], args[1], args[2], args[4]);
}
public static void upload(String hostName, String username,
String password, String localFilePath, String remoteFilePath) {
File f = new File(localFilePath);
if (!f.exists())
throw new RuntimeException("Error. Local file not found");
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create local file object
FileObject localFile = manager.resolveFile(f.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static void download(String hostName, String username,
String password, String localFilePath, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
String downloadFilePath = localFilePath.substring(0,
localFilePath.lastIndexOf("."))
+ "_downlaod_from_sftp"
+ localFilePath.substring(localFilePath.lastIndexOf("."),
localFilePath.length());
// Create local file object
FileObject localFile = manager.resolveFile(downloadFilePath);
// Create remote file object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
System.out.println("File download success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static void delete(String hostName, String username,
String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.delete();
System.out.println("Delete remote file success");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static boolean exist(String hostName, String username,
String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(
createConnectionString(hostName, username, password,
remoteFilePath), createDefaultOptions());
System.out.println("File exist: " + remoteFile.exists());
return remoteFile.exists();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static String createConnectionString(String hostName,
String username, String password, String remoteFilePath) {
// result: "sftp://user:[email protected]/resume.pdf
return "sftp://" + username + ":" + password + "@" + hostName + "/"
+ remoteFilePath;
}
public static FileSystemOptions createDefaultOptions()
throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
}
相關書籍: