简体   繁体   中英

Java FTP Download progress

I have looked at many examples and tried to understand what i`m doing wrong but with no success, maybe you can help me. It always stops at the second file, but the first one is just crated on c:\\ with 0kb size. files_server.get(i) is ArrayList with all files that i wish to download.

My code:

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;

    }}

If I use the finction:

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;
    }

instead, everything works just fine, but i can`t monitor file download progress.

I've only used it for file unzipping and not FTP, but in that case InputStream buffers can return zero, so I'd say it's worth trying changing your while loop to something like:

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

public int read(byte[] b) throws IOException

Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.

If the length of b is zero, then no bytes are read and 0 is returned;

It could also be that you're assigning count twice, which could chop the first byte off the data:

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

So don't assign anything to count when you declare it.

Let's assume your library is the FTP client from the commons-net package. It's not easy to figure out what's wrong with your code, because we can't run it and because your description (the second file stops) is not sufficient (does it throw an exception? Does it hang forever? Does it complete without any side effect?). Anyway I have a couple of advices:

  1. Use a CountingOutputStream (from Apache commons-io) to monitor progress
  2. Use a ProtocolCommandListener to log what's going on

Also, note that the first 1024 bytes are always lost. Eventually, I don't know how safe it is to put a file in C:\\ with the same name it has on the server. At the best, it could lead to permission troubles, at the worst it may originate a security flaw - anyway this doesn't hold if you have some degree of control over the filenames, but hey consider this advice.

This is a sample client

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());
    }

}

Once configured, the logger will output all the raw socket conversation, and it may help you to better understand the problem, provided it's on the FTP side and not in application IO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM