org.apache.commons.net.ftp.FTPClient を使用してサーバーにファイルをアップロードするための Java コードを実装しました。複数のファイルの場合、ftp アップロード速度が非常に遅くなります。どうすれば速度を改善できますか。
-ライブラリを変更しますか? 複数のファイルをアップロードするための強力な FTP クライアント クラス ライブラリは何ですか?
-複数のスレッドを使用しますか? 複数のスレッドで ftp アップロード機能を実装するにはどうすればよいですか? 誰かが私に例を見せてもらえますか? 私はマルチスレッドプログラミングの初心者です。
すべての回答を読んだ後、コードを変更してテストしようとします。
次に、FTPClient コードの例を示します。
// create instance of FTPClient
FTPClient ftp = new FTPClient();
ftp.setControlEncoding("UTF-8");
ftp.setDefaultTimeout(30000);
// connect to server
try
{
ftp.connect("10.1.1.1", 990);
}
catch(Exception e)
{
System.out.println("Cannot connect to server");
return;
}
// login to server
if (!ftp.login("username", "password"))
{
ftp.logout();
System.out.println("Cannot login to server");
return;
}
try
{
ftp.setFileTransferMode(FTP.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
// ftp.setBufferSize(0); <-- someone suggest me to set buffer size to 0, but it throw error sometime.
}
catch(Exception e)
{
}
// create directory on server
// dirs is list of required directories on server
for (String dir : dirs)
{
try
{
ftp.makeDirectory(dir);
}
catch(IOException e)
{
}
}
// files is a map of local file and string of remote file
// such as
// file on client is "C://test/a.txt"
// location on server is "/test/a.txt"
for (Map.Entry<File, String> entry : files.entrySet())
{
File localFile = entry.getKey();
String remoteFile = entry.getValue();
FileInputStream input = null;
try
{
input= new FileInputStream(localFile);
ftp.storeFile(remoteFile, input);
}
catch (Exception e)
{
try
{
ftp.deleteFile(remoteFile);
}
catch (IOException e1)
{
}
}
finally
{
if (input != null)
{
try
{
input.close();
}
catch (IOException e)
{
}
}
}
}
// disconnect
if (ftp != null && ftp.isConnected())
{
try
{
ftp.disconnect();
}
catch (IOException f)
{
// do nothing
}
}
1050個のファイル(各ファイルは約1〜20 KB)をアップロードすると、約49406〜51000ミリ秒かかりました(これはアップロード時間のみです)。スピードを上げたい。
ftp4j の使用を勧める人もいますが、ライブラリを 1050 ファイルでテストしたところ、ftp4j のアップロード速度は FTPClient よりも約 10000 ミリ秒遅くなりました。約60000ミリ秒かかりました。
以下は、サンプルの ftp4j コードです。
// create instance of FTPClient
FTPClient ftp = new FTPClient();
ftp.setCharset("UTF-8");
// connect to server
try
{
ftp.connect("10.1.1.1", 990);
}
catch(Exception e)
{
System.out.println("Cannot connect to server")
return;
}
// login to server
try
{
ftp.login("username", "password");
}
catch (Exception e)
{
try
{
ftp.logout();
}
catch (Exception e1)
{
}
System.out.println("Cannot login to server")
return;
}
try
{
ftp.setType(FTPClient.TYPE_BINARY);
ftp.setPassive(true);
}
catch(Exception e)
{
}
// create directory on server
// dirs is list of required directories on server
for (String dir : dirs)
{
try
{
ftp.createDirectory(dir);
}
catch (Exception e)
{
}
}
// files is a map of local file and string of remote file
// such as
// file on client is "C://test/a.txt"
// location on server is "/test/a.txt"
for (Map.Entry<File, String> entry : files.entrySet())
{
final File localFile = entry.getKey();
final String remoteFile = entry.getValue();
BufferedInputStream input = null;
boolean success = false;
try
{
input = new BufferedInputStream(new FileInputStream(localFile));
// ftp.upload(localFile); <-- if I use ftp.upload(File), it will took more time.
ftp.upload(remoteFile, input, 0, 2048, new MyTransferListener());
success = true;
}
catch (Exception e)
{
}
finally
{
if (input != null)
{
try
{
input.close();
}
catch (IOException e)
{
}
}
if (!success)
{
try
{
ftp.deleteFile(remoteFile);
}
catch (Exception e)
{
}
}
}
}
// disconnect
if (ftp != null && ftp.isConnected())
{
try
{
ftp.disconnect();
}
catch (IOException f)
{
// do nothing
}
}
複数のスレッドを使用しようとしています。
以下は、複数のスレッド コードです。
final CountDownLatch latch = new CountDownLatch(files.size());
ExecutorService pool = Executors.newFixedThreadPool(10);
for (Map.Entry<File, String> entry : files.entrySet())
{
final File localFile = entry.getKey();
final String remoteFile = entry.getValue();
pool.execute(new Runnable() {
public void run()
{
FileInputStream input = null;
try
{
input= new FileInputStream(localFile);
ftp.storeFile(remoteFile, input);
}
catch (Exception e)
{
try
{
ftp.deleteFile(remoteFile);
}
catch (IOException e1)
{
}
}
finally
{
if (input != null)
{
try
{
input.close();
}
catch (IOException e)
{
}
}
latch.countDown();
}
}
});
}
try
{
// waiting for all threads finish
// see: http://stackoverflow.com/questions/1250643/how-to-wait-for-all-threads-to-finish-using-executorservice
latch.await();
}
catch(Exception e)
{
}
それが正しいか?正しく動作しますが、速度を向上させることはできません。スレッドなしのコードと同じ約 49000 ~ 51000 ミリ秒かかりました。
イントラネットで速度をテストします。インターネット接続に時間がかかります。
アップロード速度を向上させるにはどうすればよいですか?