3

I'm using the code below to download a file. However I only want to download if the remote file is newer then the locally stored (if there is one). Can I somehow use the if-modefied-since http header? How can I update my code to archive my goal?

private class DownloadFile extends AsyncTask<String, Integer, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog.show();
    }

    @Override
    protected String doInBackground(String... sUrl) {
        try {
            URL url = new URL(sUrl[0]);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream(path);

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        }
        catch(MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch(FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        mProgressDialog.dismiss();

        // TODO: here file is downloaded and we are ready to process it.
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        mProgressDialog.setProgress(progress[0]);
    }
}

I've updated my code to look like this...

    @Override
    protected String doInBackground(String... sUrl) {
        long lastModified = new File(path).lastModified();
        try
        {
            URL url = new URL(sUrl[0]);
            URLConnection connection = url.openConnection();
            connection.connect();
            if(lastModified != 0)
            {
                connection.setIfModifiedSince(lastModified);
            }
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();
...

Any good ideas regarding how to actually test this? The while loop shouldn't run if the file isn't newer, right?

user672009
  • 4,379
  • 8
  • 44
  • 77

2 Answers2

3

That's exactly the purpose of that header. You'll want to issue an HTTP HEAD request to just get the headers, then compare the timestamp in the header to the last-modified timestamp on the file. If the server's copy is newer, issue a GET to download the new copy.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
2

What if the file is marked with a newer date but is the same on the binary level? Perhaps a better approach to the problem of downloading a newer version of file only, is to keep hashes of the file, on the server and download the hash first, then compare it with the has of your local file. If that doesn't match, then get the full file from the server. Could possibly save some bandwidth for your users if my assumption that same file can have a different (and newer) modified date holds.

Evgheni Crujcov
  • 470
  • 2
  • 8