我正在尝试从ftp服务器下载文件,但是在检索文件时卡住了。我正在使用commons-net-3.6.jar
我注意到的事情
当我使用ftpClient.enterRemotePassiveMode();
时,我在FileZilla服务器界面中看到该连接的下载进度停留在76%(688,128字节)
当我使用ftpClient.enterLocalPassiveMode();
时,我在FileZilla服务器界面中看到该连接的下载进度停留在96%(884,736字节)
有趣的是,在这两种模式下,无论文件是什么,它总是卡在相同的字节数上。如果文件大小大于884,736或688,128,它只会卡住。
对于在LocalPassiveMode中小于884,736字节和在RemotePassiveMode中小于688,128字节的文件,它非常适用。
我尝试从另一台服务器下载,但无法正常工作,因此绝对不是服务器相关问题。
我的代码
public class FTPDownload {
private List<BufferedImage> imageList;
private boolean wasConnected;
public void getFiles(String orderRootDirectory){
wasConnected = true;
imageList = new ArrayList<>();
FTPConnection con = new FTPConnection(); // to get the FTP Credentials
con.readData();
try {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(con.getServerIp());
ftpClient.enterLocalPassiveMode();
ftpClient.login(con.getUsername(), con.getPassword());
ftpClient.setAutodetectUTF8(true);
ftpClient.setBufferSize(1024 * 1024); // tried with and without this no luck there
wasConnected = ftpClient.isConnected();
FTPFile[] files = ftpClient.listFiles(orderRootDirectory);
for (FTPFile file : files) {
String details = file.getName();
if (file.isDirectory()) {
details = "[" + details + "]";
}
String totalFilePath = orderRootDirectory+"/"+file.getName();
InputStream inputStream = ftpClient.retrieveFileStream(totalFilePath); // stuck over here
System.out.println(ftpClient.completePendingCommand());
System.out.println(ftpClient.getReplyString());
System.out.println("Reading File...");
long start=System.currentTimeMillis();
ImageIO.setUseCache(false);
BufferedImage bimg = ImageIO.read(inputStream);
long end=System.currentTimeMillis();
System.out.println("time="+(end-start));
imageList.add(bimg);
details += "\t\t" + file.getSize();
details += "\t\t" + file.getName();
System.out.println(details);
}
System.out.println(imageList.size());
ftpClient.logout();
ftpClient.disconnect();
}catch (Exception e){
e.printStackTrace();
wasConnected = false;
}
}
答案 0 :(得分:2)
FTPClient#retrieveFileStream指出:
完成从InputStream的读取后,您必须关闭它。的 InputStream本身将负责关闭父数据 关闭连接插座。
和
要完成文件传输,必须调用completePendingCommand和 检查其返回值以验证成功。如果不这样做, 后续命令可能会意外。
completePendingCommand
对调用进行终结,现在,您要在终结之前执行该方法(您正在从inputStream
阅读致电completePendingCommand
之后。
您也不会关闭它特别声明的inputStream
。
要解决您的问题,请执行以下操作:首先关闭inputStream
,然后调用completePendingCommand
,所有这些都应该在 之后发生,我们已经阅读了{ {1}}。
inputStream