※ ChatGPTを利用し、要約された質問です(原文:FTPClientで転送結果(OKかFAIL))
ファイル転送結果を取得する方法とファイルアップロードの仕様について
このQ&Aのポイント
org.apache.commons.net.ftp.FTPClientを使ってファイル転送をしています。storeFileした結果を取得する方法と、ファイルアップロードの仕様について質問です。
ファイル転送時に時折ファイルサイズが0になってしまう現象が発生しています。一回目のアップロード結果を別の方法で取得することはできるでしょうか?また、複数ファイルアップロード時にログインとログアウトを繰り返す必要はあるのでしょうか?
現在の仕様ではログイン⇒処理⇒ログアウト⇒ログイン⇒処理⇒ログアウトという処理になっていますが、この処理方法がファイルアップロードの失敗の原因になっているのではないかと危惧しています。また、ftpのモードはpassvにする必要があるのでしょうか?
org.apache.commons.net.ftp.FTPClientを使ってファイル転送をしています。
storeFileした結果を取得する方法はないでしょうか。
結果がOKであれば、そのまま処理を終わり、FAILであれば再度アップロード
させたいと思っています。
上記に至った経緯は下記の通りです。
もともと、
ログイン⇒ファイルアップロード⇒ログアウト
というメソッドを作り、複数ファイルを上記メソッドを使ってアップロードして
いるのですが、時折(不定期に)ファイル転送に失敗してファイルサイズが
0になっていました。
そこで、下記のようにメソッドの仕様を変更ました。
ログイン⇒アップロード⇒アップしたファイルをダウンロードしてサイズチェック
⇒ファイルサイズが0の場合は再度アップード⇒ログアウト
すると今度は、一回目のアップロードは問題ないのに、ダウンロードが失敗
してファイルサイズが0となり、再アップロードするとファイルサイズが0になって
しまう(この時のFTPのステータスはOKでした)という現象が発生してしまい
ました。
ファイルダウンロード時にFAILになるようでは、意味がいないので、一回目の
アップロード結果を別の方法で取得できないか、というのが今回質問に至った
経緯です。
ちなみに、今の仕様だと複数ファイルアップする場合、
ログイン⇒処理⇒ログアウト⇒ログイン⇒処理⇒ログアウト・・・
という処理になっています。
これって不必要にログインとログアウトを繰り返しているように思うので、それが
ファイルアップロード失敗する一因ではと危惧しているのですが、その点もご意見
いただければ嬉しいです。
なお、
ログイン⇒ファイル1アップ⇒ファイル2アップ⇒…⇒ログアウト
に変更する場合、ftpのモードはpassvにする必要がありますか?現在はpassvではあ
りません。
参考までに、Javaソースを下記に記載しておきます。
どうぞよろしくお願いします。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
public String putFile(String filepath, byte[] bytes) throws IOException {
FTPClient ftp = null;
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = null;
try {
// FTP 接続を行う
ftp = connect();
// ファイル送信
bais = new ByteArrayInputStream(bytes);
filepath = baseDir + filepath;
// ディレクトリが存在しなければ生成する
String path = "";
String[] dirs = filepath.split("/+");
for (int i = 0; i < dirs.length - 2; i++) {
System.err.println("dirs:" + dirs[i]);
if(dirs[i].equals("")){
continue;
}
path += dirs[i] + "/";
FTPFile[] files = ftp.listFiles(path);
int j;
for (j = 0; j < files.length; j++) {
if (files[j].getName().equals(dirs[i + 1]))
break;
}
if (j < files.length)
continue;
if (!dirs[i + 1].equals("..") ){
ftp.makeDirectory(path + dirs[i + 1]);
}
}
ftp.storeFile(filepath, bais);
// ファイルサイズが0になる問題対応
// ファイルアップ後にファイルを取得してサイズが0なら再アップする
// ファイル受信
baos = new ByteArrayOutputStream();
ftp.retrieveFile(filepath, baos);
if(baos.toByteArray().length == 0)
ftp.storeFile(filepath, bais);
return filepath;
}
catch (IOException ioe) {
String msg = String.format("FTP によるファイル送信に失敗しました。(%s)", ioe.getMessage());
log.error(msg);
throw new FileTransferException(msg);
}
finally {
close(ftp, bais);
}
}
お礼
お返事ありがとうございます。 例外は発生していないので、ftpの問題と気づくまで時間がかかってしまいました。 一応try catchしているのですが… ftp(vsftp)のログを見ると下記の様にFAILとなっていたので、FTP失敗してるんだと なったわけです。 Wed Apr 4 12:10:04 2012 [pid xxxxx] [hoge] FAIL UPLOAD: Client "xxx.xxx.xxx.xxx", "/home/release/html/xxx.html", 0.00Kbyte/sec Thu Apr 5 11:00:02 2012 [pid xxxxx] [hoge] FAIL DOWNLOAD: Client "xxx.xxx.xxx.xxx", "/home/release/html/xxxx.gif", 0.00Kbyte/sec そうですね、複数アップロードの時はご指摘の通り接続をこのメソッドの外で 行うように変更する予定です。 ただ、いろいろと調べるとftpで複数ファイルアップの際はPASSIVモードじゃないと失敗する 確率が高そうな感じだったので、単にメソッドの仕様を変更するだけではだめのか??と 疑問に思っているところ(調査継続中です)です。