Download file using java apache commons?

Kyle picture Kyle · Jan 15, 2011 · Viewed 27.1k times · Source

How can I use the library to download a file and print out bytes saved? I tried using

import static org.apache.commons.io.FileUtils.copyURLToFile;
public static void Download() {

        URL dl = null;
        File fl = null;
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            copyURLToFile(dl, fl);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

but I cannot display bytes or a progress bar. Which method should I use?

public class download {
    public static void Download() {
        URL dl = null;
        File fl = null;
        String x = null;
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            OutputStream os = new FileOutputStream(fl);
            InputStream is = dl.openStream();
            CountingOutputStream count = new CountingOutputStream(os);
            dl.openConnection().getHeaderField("Content-Length");
            IOUtils.copy(is, os);//begin transfer

            os.close();//close streams
            is.close();//^
        } catch (Exception e) {
            System.out.println(e);
        }
    }

Answer

gigadot picture gigadot · Jan 15, 2011

If you are looking for a way to get the total number of bytes before downloading, you can obtain this value from the Content-Length header in http response.

If you just want the final number of bytes after the download, it is easiest to check the file size you just write to.

However if you want to display the current progress of how many bytes have been downloaded, you might want to extend apache CountingOutputStream to wrap the FileOutputStream so that everytime the write methods are called it counts the number of bytes passing through and update the progress bar.

Update

Here is a simple implementation of DownloadCountingOutputStream. I am not sure if you are familiar with using ActionListener or not but it is a useful class for implementing GUI.

public class DownloadCountingOutputStream extends CountingOutputStream {

    private ActionListener listener = null;

    public DownloadCountingOutputStream(OutputStream out) {
        super(out);
    }

    public void setListener(ActionListener listener) {
        this.listener = listener;
    }

    @Override
    protected void afterWrite(int n) throws IOException {
        super.afterWrite(n);
        if (listener != null) {
            listener.actionPerformed(new ActionEvent(this, 0, null));
        }
    }

}

This is the usage sample :

public class Downloader {

    private static class ProgressListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            // e.getSource() gives you the object of DownloadCountingOutputStream
            // because you set it in the overriden method, afterWrite().
            System.out.println("Downloaded bytes : " + ((DownloadCountingOutputStream) e.getSource()).getByteCount());
        }
    }

    public static void main(String[] args) {
        URL dl = null;
        File fl = null;
        String x = null;
        OutputStream os = null;
        InputStream is = null;
        ProgressListener progressListener = new ProgressListener();
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            os = new FileOutputStream(fl);
            is = dl.openStream();

            DownloadCountingOutputStream dcount = new DownloadCountingOutputStream(os);
            dcount.setListener(progressListener);

            // this line give you the total length of source stream as a String.
            // you may want to convert to integer and store this value to
            // calculate percentage of the progression.
            dl.openConnection().getHeaderField("Content-Length");

            // begin transfer by writing to dcount, not os.
            IOUtils.copy(is, dcount);

        } catch (Exception e) {
            System.out.println(e);
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(is);
        }
    }
}