I ran into this exact problem and wrote a simple InputStream wrapper that outputs good progress indicators:
import java.io.IOException; import java.io.InputStream; import org.apache.commons.vfs.FileContent; import org.apache.commons.vfs.FileSystemException; public class ProgressInputStream extends InputStream { private final long size; private long progress, lastUpdate = 0; private final InputStream inputStream; private final String name; private boolean closed = false; public ProgressInputStream(String name, InputStream inputStream, long size) { this.size = size; this.inputStream = inputStream; this.name = name; } public ProgressInputStream(String name, FileContent content) throws FileSystemException { this.size = content.getSize(); this.name = name; this.inputStream = content.getInputStream(); } @Override public void close() throws IOException { super.close(); if (closed) throw new IOException("already closed"); closed = true; } @Override public int read() throws IOException { int count = inputStream.read(); if (count > 0) progress += count; lastUpdate = maybeUpdateDisplay(name, progress, lastUpdate, size); return count; } @Override public int read(byte[] b, int off, int len) throws IOException { int count = inputStream.read(b, off, len); if (count > 0) progress += count; lastUpdate = maybeUpdateDisplay(name, progress, lastUpdate, size); return count; } static long maybeUpdateDisplay(String name, long progress, long lastUpdate, long size) { if (Config.isInUnitTests()) return lastUpdate; if (size < B_IN_MB/10) return lastUpdate; if (progress - lastUpdate > 1024 * 10) { lastUpdate = progress; int hashes = (int) (((double)progress / (double)size) * 40); if (hashes > 40) hashes = 40; String bar = StringUtils.repeat("#", hashes); bar = StringUtils.rightPad(bar, 40); System.out.format("%s [%s] %.2fMB/%.2fMB\r", name, bar, progress / B_IN_MB, size / B_IN_MB); System.out.flush(); } return lastUpdate; } }
(This is copied and pasted from live code, so you may need to make a few corrections to make it work in your own code.)
Then just use the InputStream input method (be sure to specify the size!) And it will make a good progress bar for you. If you need the right callback, that will be pretty easy to do too.
source share