Java FTP接続でファイル送信・ファイル受信する方法
JavaでFTP接続でファイル送信・ファイル受信する方法です。
JavaでFTPするためには Apache Commons Net を利用します。
ここでは JavaでFTP接続でファイル送信・ファイル受信する方法 をサンプルソースで紹介します。
目次
環境構築
・Apache Commons Net - Download Commons Net
ここでは commons-net-3.3.jar をダウンロードして利用しています。
Mavenプロジェクトの場合はpom.xmlに下記を追加で。
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
FTP送受信サンプルソース
FTP送受信のサンプルソースです。ここでは FtpConfig という Bean と Ftp というクラスを用意しています。説明はサンプルソースの後に記載しています。
FtpConfigクラス
FtpConfigは、FTP定義 Bean です。
package ftp;
import java.io.Serializable;
/**
* <p><strong>FtpConfig</strong>は、FTP定義 Bean です。</p>
*/
public class FtpConfig implements Serializable {
private static final long serialVersionUID = 1L;
public String hostName;
public int port;
public String userName;
public String password;
public boolean binaryTransfer;
public boolean usePassiveMode;
public String hostPath;
public String localPath;
public String encoding;
}
Ftpクラス
Ftpは、FTPをおこなうクラスです。
package ftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
/**
* <p><strong>Ftp</strong>は、FTPをおこなうクラスです。</p>
* <p>利用方法:</p>
* <pre>
* try {
* Ftp ftp = new Ftp("192.168.0.100", 21, "sakaen", "password", false, false, "/home/sakaen", "C:/Temp/", "EUC_JP");
* if ( ftp.connect() )
* ftp.put();
* ftp.disconnect();
* } catch (Exception e) {}
* </pre>
* <p>ローカル側パスへは C:/Temp/sakaen.txt などのファイル名指定も可能です。</p>
*
* @author Sakakibara Engineering Office.
* @version $Revision: 1.0 $ $Date: 2015.02.01 $ $Description: 新規作成 $
*/
public class Ftp {
private FtpConfig config;
private FTPClient client;
private boolean isConnected;
/**
* コンストラクタ
*
* @param config FtpConfig
*/
public Ftp(FtpConfig config) {
this.config = config;
this.isConnected = false;
}
/**
* コンストラクタ
*
* @param hostName ホスト名(IPアドレス:127.0.0.1)
* @param port ポート番号(21)
* @param userName ユーザー
* @param password パスワード
* @param binaryTransfer バイナリ転送モード(true: Yes, false: No)
* @param usePassiveMode パッシブモード(true: Yes, false: No)
* @param hostPath ホスト側パス
* @param localPath ローカル側パス
* @param encoding エンコーディング(SJIS, MS932, EUC_JP など)
*/
public Ftp(String hostName, int port, String userName, String password, boolean binaryTransfer, boolean usePassiveMode, String hostPath, String localPath, String encoding) {
this.config = new FtpConfig();
this.config.hostName = hostName;
this.config.port = port;
this.config.userName = userName;
this.config.password = password;
this.config.binaryTransfer = binaryTransfer;
this.config.usePassiveMode = usePassiveMode;
this.config.hostPath = hostPath;
this.config.localPath = localPath;
this.config.encoding = encoding;
this.isConnected = false;
}
/**
* パラメータチェック
*
* @return true: 正常, false: 異常
*/
private boolean check() {
boolean success = true;
// ホスト名
if ( isEmpty(this.config.hostName) ) {
System.out.println("hostName Parameter Failed");
success = false;
}
// ポート
if ( this.config.port == 0 ) {
System.out.println("port Parameter Failed");
success = false;
}
// ユーザー名
if ( isEmpty(this.config.userName) ) {
System.out.println("userName Parameter Failed");
success = false;
}
// パスワード
if ( isEmpty(this.config.password) ) {
System.out.println("password Parameter Failed");
success = false;
}
// ホストパス
if ( isEmpty(this.config.hostPath) ) {
System.out.println("hostPath Parameter Failed");
success = false;
}
// ローカルパス
if ( isEmpty(this.config.localPath) ) {
System.out.println("localPath Parameter Failed");
success = false;
}
if ( isEmpty(this.config.encoding) ) {
System.out.println("encoding Parameter Failed");
success = false;
}
return success;
}
/**
* 接続
*
* @return true: 正常, false: 異常
* @throws Exception
*/
public boolean connect() throws Exception {
boolean success = check();
if ( !success )
return false;
this.client = new FTPClient();
System.out.println("connect....");
this.client.setControlEncoding(this.config.encoding);
client.connect(this.config.hostName, this.config.port);
System.out.println("Connected to Server: " + this.config.hostName + " on " + this.client.getRemotePort());
System.out.println(this.client.getReplyString());
this.client.login(this.config.userName, this.config.password);
System.out.println(client.getReplyString());
if ( !FTPReply.isPositiveCompletion(this.client.getReplyCode()) ) {
System.out.println("Login Failed");
this.client.disconnect();
return false;
} else {
this.isConnected = true;
}
// Binary転送モードの場合
if ( this.config.binaryTransfer ) {
this.client.setFileType(FTP.BINARY_FILE_TYPE);
System.out.println("Mode binaryTransfer: true");
}
// PASVモードの場合
if ( this.config.usePassiveMode ) {
this.client.enterLocalPassiveMode();
System.out.println("Mode usePassiveMode: ON");
} else {
this.client.enterLocalActiveMode();
System.out.println("Mode usePassiveMode: OFF");
}
// ディレクトリ移動
success = this.client.changeWorkingDirectory(this.config.hostPath);
if ( !success ) {
System.out.println("Server Directory Failed");
this.client.disconnect();
return false;
}
System.out.println(this.client.getReplyString());
success = FTPReply.isPositiveCompletion(this.client.getReplyCode());
System.out.println("Connection: " + (success ? "OK" : "NG"));
System.out.println("-----------------------------------");
return success;
}
/**
* 切断
*
* @return true: 正常, false: 異常
* @throws Exception
*/
public boolean disconnect() throws Exception {
if ( this.isConnected ) {
client.logout();
System.out.println(client.getReplyString());
if ( client.isConnected() ) client.disconnect();
}
return true;
}
/**
* 送信
*
* @return true: 正常, false: 異常
* @throws Exception
*/
public boolean put() throws Exception {
boolean success = true;
if ( !this.isConnected )
success = connect();
if ( success ) {
// ディレクトリ移動
success = this.client.changeWorkingDirectory(this.config.hostPath);
if ( !success ) {
System.out.println("Server Directory Failed");
this.client.disconnect();
return false;
}
return putFiles(new File(this.config.localPath), this.config.hostPath + (this.config.hostPath.endsWith("/") ? "" : "/"));
}
return success;
}
/**
* ファイル送信
*
* @param file FTPFile
* @param hostPath ホスト側パス
* @throws Exception
*/
private boolean putFiles(File file, String hostPath) throws Exception {
boolean success = true;
if ( file.isFile() ) {
FileInputStream is = null;
try {
is = new FileInputStream(file);
System.out.println("PUT File Name: " + file.getName());
this.client.storeFile(hostPath + file.getName(), is);
is.close();
System.out.println("FTP PUT Completed");
} catch ( Exception e ) {
System.out.println("FTP PUT Failed: " + file.getName());
System.out.println(e.getMessage());
success = false;
} finally {
if ( is != null )
is.close();
}
} else if ( file.isDirectory() ) {
String dirName = hostPath + file.getName() + "/";
System.out.println("Make Directory: " + dirName);
// ディレクトリがなければ作る
success = this.client.makeDirectory(dirName);
if ( success ) {
success = this.client.changeWorkingDirectory(dirName);
} else {
// ディレクトリが作れない場合、移動してみる
success = this.client.changeWorkingDirectory(dirName);
if ( !success ) {
System.out.println("Server Directory Failed: " + dirName);
return success;
}
}
System.out.println("-----------------------------------");
File[] files = file.listFiles();
for ( File f : files ) {
success = putFiles(f, dirName);
if ( !success )
return success;
}
} else {
}
return success;
}
/**
* 受信
*/
public boolean get() throws Exception {
boolean success = true;
if ( !this.isConnected )
success = connect();
if ( success ) {
// ディレクトリ移動
success = this.client.changeWorkingDirectory(this.config.hostPath);
if ( !success ) {
System.out.println("Server Directory Failed");
this.client.disconnect();
return false;
}
String fileNames[] = this.client.listNames();
if ( fileNames != null ) {
for ( int i = 0; i < fileNames.length; i++ ) {
System.out.println("Get File Name: " + fileNames[i]);
}
}
System.out.println("-----------------------------------");
for (FTPFile f : this.client.listFiles()) {
getFiles(f, this.config.localPath);
}
}
return success;
}
/**
* ファイル取得
*
* @param file FTPFile
* @param localPath ローカル側パス
* @throws Exception
*/
private boolean getFiles(FTPFile file, String localPath) throws Exception {
boolean success = true;
if ( !file.getName().equals(".")&&!file.getName().equals("..") ) {
String currentDir = client.printWorkingDirectory();
if ( file.isFile() ) {
String filename = file.getName();
filename = new String(filename.getBytes("MS932"), "UTF-8");
String utf8filename = client.printWorkingDirectory() + (currentDir.endsWith("/") ? "" : "/") + file.getName();
System.out.println("Get File Name: " + filename);
System.out.println("Get UTF8 File Name: " + utf8filename);
String localPathName = localPath + (localPath.endsWith("/") ? "" : "/") + filename;
System.out.println("Local Path Name: " + localPathName);
FileOutputStream os = null;
try {
os = new FileOutputStream(localPathName);
client.retrieveFile(utf8filename, os);
os.close();
System.out.println("FTP GET Completed");
} catch ( Exception e ) {
System.out.println("FTP GET Failed: " + filename);
System.out.println(e.getMessage());
success = false;
} finally {
if ( os != null )
os.close();
}
} else if ( file.isDirectory() ) {
File localDir = new File(localPath + (localPath.endsWith("/") ? "" : "/") + file.getName());
String path = localPath;
if ( !localDir.exists() ) {
localDir.mkdirs();
path = localPath + (localPath.endsWith("/") ? "" : "/") + file.getName();
}
success = client.doCommand("CWD", client.printWorkingDirectory() + (currentDir.endsWith("/") ? "" : "/") + file.getName());
for (FTPFile f : client.listFiles()) {
success = getFiles(f, path);
if ( !success )
break;
}
//client.doCommand("CDUP", "");
}
}
return success;
}
/**
* 空文字列チェック
*
* @param value 文字列
* @return null または 空文字列 なら true , それ以外なら false
*/
public boolean isEmpty(String value) {
if ( value == null || value.length() == 0 )
return true;
else
return false;
}
/**
* ホスト側パスセット
*
* @param hostPath ホスト側パス
*/
public void setHostPath(String hostPath) {
this.config.hostPath = hostPath;
}
/**
* ローカル側パスセット
*
* @param localPath ローカル側パス
*/
public void setLocalPath(String localPath) {
this.config.localPath = localPath;
}
}
サンプルソースの説明
まず FTPClient をインスタンス化し setControlEncoding メソッドにてエンコードを設定します。次に connect メソッドを使って指定サーバーへ接続します。login メソッドを使ってログインすれば、ファイルを送信したり受信したりできます。
ファイルを送信する場合 storeFile メソッドの引数に FileInputStream を指定します。サンプルソースの putFiles メソッドでは、FTPサーバ上に指定ディレクトリがない場合、新規に作成しています。
ファイルを受信する場合 retrieveFile メソッドの引数に ファイル名と FileOutputStream を指定します。サンプルソースの getFiles メソッドでは、ローカル上に指定ディレクトリがない場合、新規に作成しています。
FTPClientの主なメソッド
サンプルソースで使った FTPClient の主なメソッドです。
メソッド | 説明 |
---|---|
setControlEncoding | エンコーディング(SJIS, MS932, EUC_JPなど)を指定します。 |
connect | IPアドレスやコンピュータ名、ポート番号を指定してFTPサーバーへ接続します。 |
login | ユーザー名、パスワードを指定してFTPサーバーへログインします。 |
setFileType | 転送モードを指定します。(BINARY_FILE_TYPE or ASCII_FILE_TYPE) |
enterLocalPassiveMode | PASVモードの場合、メソッドを呼び出します。 |
enterLocalActiveMode | PASVモード以外の場合、メソッドを呼び出します。 |
changeWorkingDirectory | ディレクトリを移動します。 |
logout | ログアウトします。 |
isConnected | FTPサーバーへ接続されているかどうかを判断します。 |
disconnect | FTPサーバーへの接続を切断します。 |
storeFile | FTPサーバーへファイルを送信します。 |
printWorkingDirectory | 現在の作業ディレクトリのパス名を返します。 |
retrieveFile | FTPサーバーからファイルを受信します。 |
doCommand | コマンドを発行し、応答を待ちます。 |
FTP送受信テスト
それでは FTP送受信のテストをしてみましょう。テストソースはこんな感じです。
public class FtpTest {
public static void main(String[] args) {
try {
Ftp ftp = new Ftp("192.168.0.100", 21, "sakaen", "password", false, false, "/home/sakaen", "C:/Temp/", "EUC_JP");
if ( ftp.connect() ) {
ftp.get();
ftp.setLocalPath("C:/Temp/サカエン");
ftp.put();
ftp.disconnect();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Ftp クラスへのパラメーターは環境に合わせて変更してください。
まず、FTPサーバー上からファイルを受信します。次に、ローカルのディレクトリを移動してFTPサーバへファイルを送信します。
ローカル側のディレクトリ内
ローカル側のディレクトリ内の状態を確認しましょう。
C:/Temp の中には サカエン というディレクトリのみ存在します。
C:/Temp/サカエン の中には saka-en というディレクトリと サカエン.txt というファイルが存在します。
C:/Temp/サカエン/saka-en の中には saka-en.txt というファイルが存在します。
FTPサーバ側のディレクトリ内
FTPサーバ側のディレクトリ内状態を確認しましょう。
/home/sakaen の中には Test というディレクトリが存在します。
/home/sakaen/Test の中には Test2 というディレクトリと text1.txt というファイルが存在します。
/home/sakaen/Test/Test2 の中には text2.txt というファイルが存在します。
FTP送受信テスト結果
実行結果はこんな感じになります。
ローカル側
C:/Temp/Test というディレクトリが増えました。
C:/Temp/Test の中には Test2 ディレクトリと text1.txt ファイルが存在します。
C:/Temp/Test/Test2 の中には text2.txt ファイルが存在します。
FTP受信がうまくいったようですね。
FTPサーバー側
/home/sakaen の中には サカエン というディレクトリが増えました。
/home/sakaen/サカエン の中には saka-en ディレクトリと サカエン.txt ファイルが存在します。
/home/sakaen/サカエン/saka-en の中には saka-en.txt ファイルが存在します。
FTP送信がうまくいったようですね。
参考サイト
おつかれさまでした。