-
1. Re: How to detect file download has been cancelled?
kragoth Jul 2, 2009 2:42 AM (in response to gturek)I dont think you can actually detect it client side. I could be wrong but I don't think you can.
I'm not sure if this is a possible solution as I'm just thinking out loud here. But, couldn't you go to the servlet that delivers your files and get it to write to the database only if the entire stream is sent. If the user aborts the connection then your stream wont complete and thus you don't write to the database.
I don't know how you do this, but it's just something I'm thinking about. Maybe you can see if this will work for you.
-
2. Re: How to detect file download has been cancelled?
gturek Jul 2, 2009 6:18 AM (in response to gturek)That was my thinking too, and I was hoping that canceling would cause an IOException but it does not seem to be the case. I will have to track the amount of bytes sent... Hum
Gaby -
3. Re: How to detect file download has been cancelled?
kragoth Jul 3, 2009 1:30 AM (in response to gturek)Could you let us know how you go with this please?
I know I would be interested in seeing a solution, and I'm sure a lot of other people would be interested too.Cheers,
Tim -
4. Re: How to detect file download has been cancelled?
gturek Jul 3, 2009 2:02 AM (in response to gturek)You can be sure if I have a breakthru you'll know about it. Well, the approach of tracking bytes sent does not work. the moment the user the hits the download link the whole file is copied from input stream to output stream in one go. Cancelling arrives too late, so to speak. Here is my code, for sanity sake. The next step is to go into debug mode I suppose and see what exactly happens when one hits cancel. Is there another
way to do a download perhaps?
public void downloadModule(Module selectedModule) throws ModuleProcessingException {
... Stuff here to get Uri of file ----
File outGoing = new File(archiveRoot + "/" + uri);
long fileSize = outGoing.length();
HttpServletResponse response = (HttpServletResponse) extCtx.getResponse();
response.setContentType("text/plain"); // Placeholder
response.addHeader("Content-disposition", "module; filename=\"" + fileName + "\"");
ServletOutputStream out = null;
FileInputStream in = null;
try {
out = response.getOutputStream();
in = new FileInputStream(outGoing);
int bytesWritten = FileUtils.copy(in, out);
System.out.println("********** bytesWritten " + bytesWritten);
out.flush();
out.close();
in.close();
facesContext.responseComplete();
//Doesn't work! copying happens as soon as link is clicked...
if (bytesWritten == fileSize) {
downloadRecord = new DownloadRecord();
downloadRecord.setModuleVersion(moduleVersion);
downloadRecord.setDownloadDate(new Date(System.currentTimeMillis()));
downloadRecord.setDownloadedBy("auser"); // TODO: get user
entityManager.persist(downloadRecord);
}
} catch (Exception e) {
log.fatal("Exception while downloading " + module.getModuleId() + ": " + e.getMessage());
throw new ModuleProcessingException(e.getMessage());
} finally {
try {
in.close();
out.close();
} catch (IOException ioe) {
// Nothing to do
}
}
The FileUtils.copy code
public static int copy(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[1024 * 1024];
int total = 0;
for (int i = is.read(buffer); i > -1; i = is.read(buffer)) {
os.write(buffer, 0, i);
total += i;
}
return total;
} -
5. Re: How to detect file download has been cancelled?
luxspes Jul 3, 2009 4:44 PM (in response to gturek)
Gabriella Turek wrote on Jul 03, 2009 02:02:
You can be sure if I have a breakthru you'll know about it. Well, the approach of tracking bytes sent does not work. the moment the user the hits the download link the whole file is copied from input stream to output stream in one go.That is... not entirely accurate, you should say: the moment the user the hits the download link I copy the whole file, and after I finish I try to see if it was sent ;-). You make it that way, with the line:
int bytesWritten = FileUtils.copy(in, out);
That is when your code
copies the whole file in one go
, inside FileUtils.copy you do that with a loop (guess that is when you could detect if something is failing, perhaps by flushing each time you send a chunk of the file to the response)And then you even say that you only one to flush at the and... and that you have finished responding:
out.flush(); out.close(); in.close(); facesContext.responseComplete();
Any checking you do after that is pointless. You have already told the system that
the response is Complete
-
6. Re: How to detect file download has been cancelled?
gturek Jul 6, 2009 1:49 AM (in response to gturek)Yep, you're absolutely right, I need to tweak my copy code and see if I can detect an interrupt. I tried it before expecting some kind of IOException but nothing. Perhaps I need to copy smaller chunks and flush more often, I'll give a go when I get back to work (sick now)
-
7. Re: How to detect file download has been cancelled?
gturek Jul 29, 2009 2:31 AM (in response to gturek)Still working on this. It turns out that without the facesContext.responseComplete(); line the code does not work. I get the error message
An Error Occurred:
Servlet response already use stream, Writer not possibleand never get the download popup.
So I am completely stumped.
Gaby