gpt4 book ai didi

java - 如何提高多个文件的 ftp 上传速度 [Java]

转载 作者:搜寻专家 更新时间:2023-11-01 03:39:42 25 4
gpt4 key购买 nike

我使用 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 毫秒,与没有线程的代码相同。

我用内网测试速度。上网需要更多时间。

如何提高上传速度?

最佳答案

我不知道为什么,但是 Apache Commons FTP 上传很慢,我遇到了同样的问题,我无法解决。

现在我使用 FTP4j , 它与 apache commons ftp 非常相似,但上传速度非常快。

这是一个例子:

FTPClient client = new FTPClient();
client.connect("www.yoursite.com");
client.login("login", "password");
client.setPassive(true);
client.setType(FTPClient.TYPE_BINARY);
client.changeDirectory("a");
File f = new File("path/to/your/file");
client.upload(f);
client.disconnect(true);

使用这个库,我在不到一秒的时间内上传了一个 340KB 的文件,而使用 Apache Commons FTP 大约需要 1 分钟。

如果您想使用线程传输不同的文件,请尝试将每个 client.upload(f) 放入不同的线程,但我不确定它是否会提高传输速度。


引用@fge之前的回答:

基本上,您很可能做不到。

不要忘记 FTP 有两种类型的 channel :命令 channel 和数据通道。一次上传是通过在命令 channel 上发送指令来为上传本身打开一个数据通道来启动的。

现在:

  • 大多数 FTP 服务器的配置使得一个命令 channel 在任何时候只能打开一个数据通道;
  • 存在带宽限制:您的上行带宽和服务器的下行带宽。

如果可以并行上传多个文件,即打开多个数据通道,您会遇到一个问题,即 TCP 本身的开销实际上通常会减慢上传过程。

基本上:随时保持一个数据通道打开。尝试打开不止一个是不值得的。一般而言,它可能适用于约 1% 的情况。这是不值得的麻烦。

关于java - 如何提高多个文件的 ftp 上传速度 [Java],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17511322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com