Java FTP下载进度

时间:2012-08-15 07:48:55

标签: java ftp download

我看了很多例子并试图了解我做错了什么但没有成功,也许你可以帮助我。它总是在第二个文件处停止,但第一个文件只是在c:\上创建,大小为0kb。 files_server.get(i)是ArrayList,包含我想下载的所有文件。

我的代码:

public FTPConnection() {

StartD std = new StartD();
std.start();
}

class StartD extends Thread{

        @Override
        public void run()
        {
        for (int i = 0; i < files_server.size(); i++) {
            err = ftpDownload(files_server.get(i), "C:/"+ files_server.get(i)); 
            if (!err) 
                {
                System.out.println("Error in download, breaking");
                break;
                }
            }
        }

        public boolean ftpDownload(String srcFilePath, String desFilePath) 
        {
        try {
            FileOutputStream desFileStream = new FileOutputStream(desFilePath);
            InputStream input = mFTPClient.retrieveFileStream(srcFilePath);
            byte[] data = new byte[1024];
            int count;
            while ((count = input.read(data)) != -1) 
            {
                desFileStream.write(data, 0, count);
            }
            desFileStream.close();

        } catch (Exception e) {

            return false;
        }
    return true;

    }}

如果我使用了结尾:

public boolean ftpDownload(String srcFilePath, String desFilePath) {
        boolean status = false;
        try {

            FileOutputStream desFileStream = new FileOutputStream(desFilePath);
            status = mFTPClient.retrieveFile(srcFilePath, desFileStream);
            desFileStream.close();
            return status;
        } catch (Exception e) {

        }
        return status;
    }

相反,一切正常,但我无法监控文件下载进度。

2 个答案:

答案 0 :(得分:2)

我只使用它来解压缩文件而不是FTP,但是在这种情况下,InputStream缓冲区可以返回零,所以我认为值得尝试将while循环更改为:

while ((count = input.read(data)) >= 0)
  

public int read(byte [] b)抛出IOException

     

从输入流中读取一些字节数并将它们存储到缓冲区数组b中。   实际读取的字节数以整数形式返回。这个   方法阻塞直到输入数据可用,检测到文件结尾,   或抛出异常。

     

如果b的长度为零,则不读取任何字节,返回0;

也可能是你分配了两次计数,这可能会破坏数据的第一个字节:

int count  = input.read(data);
while ((count = input.read(data)) != -1)

因此,在声明它时不要指定任何可计数的内容。

答案 1 :(得分:1)

假设您的库是commons-net包中的FTP客户端。要弄清楚你的代码有什么问题并不容易,因为我们无法运行它,因为你的描述(第二个文件停止)是不够的(它会抛出异常吗?它会永远挂起吗?它是否完整而没有任何副作用?)。无论如何,我有几个建议:

  1. 使用CountingOutputStream(来自Apache commons-io)监控进度
  2. 使用ProtocolCommandListener记录正在进行的操作
  3. 另请注意,前1024个字节始终丢失。最后,我不知道将文件放在C:\中的安全性与它在服务器上的名称相同。在最好的情况下,它可能会导致许可问题,最坏的情况可能会导致安全漏洞 - 无论如何,如果您对文件名有一定程度的控制权,这并不成立,但是他们会考虑这个建议。

    这是一个示例客户端

    public class FTP {
    
        public static void main(String[] args) throws SocketException, IOException {
            FTPClient client = new FTPClient();
    
            client.addProtocolCommandListener(new ProtocolCommandListener(){
    
                @Override
                public void protocolCommandSent(ProtocolCommandEvent evt) {
                    logger.debug(evt.getMessage());
    
                }
    
                @Override
                public void protocolReplyReceived(ProtocolCommandEvent evt) {
                    logger.debug(evt.getMessage());
                }
    
            });
    
            client.connect("ftp.mozilla.org");
            client.login("anonymous", "");
            client.enterLocalPassiveMode();
    
            OutputStream out = new CountingOutputStream(new NullOutputStream()) {
                @Override
                public void beforeWrite(int count) {
                    super.beforeWrite(count);
                    logger.info("Downloaded " + getCount() + " bytes");
                }
            };
    
            for (String filename: new String[] {"MD5SUMS", "SHA1SUMS"})
                client.retrieveFile("pub/firefox/releases/15.0b4/" + filename, out);
    
            out.close();
            client.disconnect();
        }
    
        private static Logger logger;
    
        static  {
            logger = Logger.getLogger(FTP.class.getCanonicalName());
        }
    
    }
    

    配置完成后,记录器将输出所有原始套接字会话,它可以帮助您更好地理解问题,只要它在FTP端而不是在应用程序IO中