1

我看过很多例子并试图理解我做错了什么但没有成功,也许你可以帮助我。它总是停在第二个文件上,但第一个文件只是在 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;
    }

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

4

2 回答 2

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)

所以当你声明它时不要分配任何东西来计数。

于 2012-08-15T08:01:38.990 回答
1

假设您的库是 commons-net 包中的 FTP 客户端。找出你的代码出了什么问题并不容易,因为我们无法运行它,而且你的描述(第二个文件停止)是不充分的(它会抛出异常吗?它会永远挂起吗?它是否在没有任何方面完成影响?)。无论如何,我有几个建议:

  1. 使用CountingOutputStream(来自 Apache commons-io)来监控进度
  2. 使用 aProtocolCommandListener记录正在发生的事情

另外,请注意前 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 中

于 2012-08-15T14:49:26.123 回答