I have a Java program running as jar. When it's running, I want to detect download of a file from browser to Downloads folder. I can detect using Java nio package WatchService but the problem is with this I can detect only the addition of new file to Downloads folder. I can't detect when download or copy finishes.
Is there a way I can detect the download (or addition) of a file to a directory (e.g. Downloads) when it finishes?
CodePudding user response:
I just tried the WatchService for the first time, but I do get all the events I was looking for. Here is my code and the output whilst downloading some file with my browser:
import java.nio.file.*;
public class Test {
public static void main(String[] args) throws Exception {
Path path = Paths.get("/home/hiran/Downloads");
WatchService watchService = path.getFileSystem().newWatchService();
WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
for (WatchEvent<?> event: key.pollEvents()) {
System.out.println("Received " event.kind() " on " event.context());
}
}
}
}
And here is the output I received during a download:
Received ENTRY_CREATE on fA-3bH63.tgz.part
Received ENTRY_MODIFY on fA-3bH63.tgz.part
Received ENTRY_CREATE on oolite-1.90.linux-x86_64.tgz
Received ENTRY_DELETE on fA-3bH63.tgz.part
Received ENTRY_CREATE on oolite-1.yrfZFKKr.90.linux-x86_64.tgz.part
Received ENTRY_MODIFY on oolite-1.yrfZFKKr.90.linux-x86_64.tgz.part
Received ENTRY_MODIFY on oolite-1.yrfZFKKr.90.linux-x86_64.tgz.part
...
Received ENTRY_MODIFY on oolite-1.yrfZFKKr.90.linux-x86_64.tgz.part
Received ENTRY_DELETE on oolite-1.yrfZFKKr.90.linux-x86_64.tgz.part
Received ENTRY_CREATE on oolite-1.90.linux-x86_64.tgz
Received ENTRY_MODIFY on oolite-1.90.linux-x86_64.tgz
So there is no clear event saying 'download has finished', but there is a pattern you could use.
As soon as a file got created/modified, wait for a few seconds. If there is no further such event, assume the download has finished and process it. To be even more on the safe side, try to open the file with exclusive access to be sure no other process is still writing, only then process it.
CodePudding user response:
Is there a way I can detect the download (or addition) of a file to a directory (e.g. Downloads) when it finishes?
Not reliably.
While the Linux inotify
API includes an event that corresponds to the closing of a file that was being written, this is not supported by the standard Java WatchService
. So while you can use the WatchService
to detect the creation of a downloaded file, you can't use it to detect that the download has completed.
So you need to try to infer that the download has completed:
If the download mechanism writes the file to a file with a temporary name and renames it on completion, then look for the rename event.
Otherwise, you can poll the "last modified" timestamp for the file. If the file stop changes, you could assume that the download has completed.
There are problems with both of these. The download mechanism may not rename the downloaded file, and downloads can stall and resume due to network congestion.