原文链接:http://pro.ctlok.com/2011/06/apache-commons-vfs-for-sftp.html
在 Java 使用 FTP 去上載檔案,下載檔案或去做其他操作也是很簡單,因為 Java API 已經包括了對 FTP 的支援。如果不是使用 FTP,而是使用 SFTP: SSH File Transfer Protocol,使用Java API 實作便有點麻煩了。
幸好 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:123456@domainname.com/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:123456@domainname.com/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;
- }
-
- }