1

In a program I have that auto-updates, I need it to download a specific file (working already) and it does so with the following code:

public static void getFile() {
    try {
        URL url = new URL("https://dl.dropboxusercontent.com/s/tc301v61zt0v5cd/texture_pack.png?dl=1");
        InputStream in = new BufferedInputStream(url.openStream());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int n = 0;
        while (-1 != (n = in.read(buf))) {
            out.write(buf, 0, n);
        }
        out.close();
        in.close();
        byte[] response = out.toByteArray();
        FileOutputStream fos = new FileOutputStream(file4);
        fos.write(response);
        fos.close();
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, "Check your internet connection, then try again.\nOr re-install the program.\nError Message 7", "Could Not Download The Required Resources.", JOptionPane.NO_OPTION);
        e.printStackTrace();
        System.exit(0);
    }
}

How would I implement a way to get the current completion of the download (like the percent it's downloaded) and put it into an integer to be printed out in the console (just for developer testing). Also what sort of equation could i use to get the estimated amount of time left on the download? Anything would help! Thanks.

Bryce Hahn
  • 1,585
  • 4
  • 16
  • 26

2 Answers2

4

If you examine the HTTP headers sent in the file download, you'll discover the file size. From this you can calculate percentage complete:

curl --head "https://dl.dropboxusercontent.com/s/tc301v61zt0v5cd/texture_pack.png?dl=1"

Gives you this:

HTTP/1.1 200 OK
accept-ranges: bytes
cache-control: max-age=0
content-disposition: attachment; filename="texture_pack.png"
Content-length: 29187
Content-Type: image/png
Date: Mon, 28 Apr 2014 22:38:34 GMT
etag: 121936d
pragma: public
Server: nginx
x-dropbox-request-id: 1948ddaaa2df2bdf2c4a2ce3fdbeb349
X-RequestId: 4d9ce90907637e06728713be03e6815d
x-server-response-time: 514
Connection: keep-alive

You may have to use something more advanced than standard Java library classes for your download to access the headers however, something like Apache HttpClient.

maksimov
  • 5,792
  • 1
  • 30
  • 38
  • 1
    Clever, didn't think of that. I'm pretty sure that you don't need to go with HttpClient (though you should, it's very handy), the standard class HttpUrlConnection contatins everything you need (though it's unwieldy). Also, it will work only if it's a download, not if it's streaming. – Paul Hicks Apr 28 '14 at 22:44
  • 1
    I always use HttpClient, so wasn't sure about the UrlConnection hence 'you may have' :-) Good to know! – maksimov Apr 28 '14 at 22:45
2

There is no way to get the size of a streamed file without streaming to the end of the file, so it can't be done within that block of code.

If you are willing to adopt the Dropbox API, you can use that to get the size of the file before starting the download. Then you can work with that size and the number bytes downloaded (n in your code) to achieve what you need.

The class in the Dropbox API that you need is DbxEntry.File.

Paul Hicks
  • 13,289
  • 5
  • 51
  • 78
  • This is the correct answer but to clarify one bit -- OP is reading from an InputStream object. In order to know what percentage complete the file is, OP would need to know total file size, and how many bytes (cumulatively) read so far. Knowing the total file size simply isn't possible ahead of time with an InputStream. The Dropbox API is a good suggestion if OP is using a lot of files from there. Otherwise it might be overkill. – FrobberOfBits Apr 28 '14 at 22:42