views:

590

answers:

6

We've been looking for a while for an answer to this, but haven't found a solution.

We have a web server, which allows the user to download files (pdfs), which are dynamically-generated and served from servlets. We'd like to know when a download has completed (and how: was it successful, did it fail, did the user cancel?).

Is there a way to know this without user input? These files are relatively small so no progress-bar functionality is needed, but we need some sort of "end-hook" which reports back when the download has finished. Is this possible?

[edit] What capability would there be on the browser-side that can detect end-of-download and report back to the server via ajax?

+1  A: 

Unless you get a network error, you cannot know. The only way is to have the browser to send a second event to the server (using AJAX) to acknowledge the download was completed successfully.

David Rabinowitz
How would the browser know if the download is completed successfully? That was the gist of my question in fact, I'll edit to make it clearer
laura
Why was this answer accepted? We still don't know how can the browser know the download is completed
abyx
+1  A: 

Even though the files are small, if you use the setContentLength method of ServletResponse the user will be able to distinguish between an error and a good download, and their browser's download manager will tell them when it's complete.

Jim Downing
+2  A: 

User cancelling can sometimes be detected in a servlet. Using Tomcat for example, try to stream a large file to the client, and then cancel the download. You can see the stacktrace of the exception in logs/catalona.out. I'm not sure, however, that this can be handled in servlet itself or a lower level (inside catalina).

There is a preloading approach (sure with event listener facility) usually used to download images. It's up to the browser to download the whole PDF or not if it detects it as an unsupported image, but it worths giving a try. Here is an example.

Another solution would be to implicitly download the PDF using <object> or <embed> tags, and using their onload event listener. Not that this only works if an ActiveX or some sort of PDF file association is done in the browser, and probably won't work if user doesn't have a PDF viewer. Here is an example demonstrating this (see assisted solution: 11/21/04 08:22 AM, ID: 12638846).

Mohsen

Mohsen
+3  A: 

You can get a pretty good idea from the server which is connected to the browser directly (the endpoint of TCP connection). The server will get IO error when user cancels download or encounters any network problem. So if you can run the server directly (without proxies). You can do something like this,

  try {
      response.setContentType("application/pdf");
      response.setContentLength(bytes.length);
      ServletOutputStream ouputStream = response.getOutputStream();
      ouputStream.write(bytes, 0, bytes.length);
      ouputStream.flush();
      ouputStream.close();
      logger.info("PDF " + fileName + " sent successfully");
  } catch (Exception e) {
      logger.error("PDF " + fileName + " error: " + e.getMessage());
      throw e;
  }

However, there is still a small chance that the user may not see the PDF in browser after successful download. ACK from browser will be best approach. You can't do that if PDF is displayed by browser directly. You have to use some kind of Javascript PDF viewer and add a call back to server when it's displayed.

ZZ Coder
+1  A: 

The browser natively does not handle this but you could use google gears to handle the download request (it would fire a success event when the download has been completed).

http://code.google.com/apis/gears/api%5Fhttprequest.html

Ben Rowe
A: 

If you can insert an image field in your documents, the image href can point back to your server to confirm that the user has opened the pdf document.

I haven't tried this myself but looking at the last page of this adobe doc seems possible.

If you are using Itext it does not support the image fields, but you can use a pdf template with the image field to build your documents and add the javascript to assign the url to the image field.

Serhii