Java Sonatype异步HTTP客户端上载进度

时间:2012-05-13 16:13:21

标签: java file-upload asynchronous progress

我正在尝试使用sonatype async http client - https://github.com/sonatype/async-http-client进行异步文件上传。

我尝试了文档中建议的方法。使用转移监听器。 http://sonatype.github.com/async-http-client/transfer-listener.html

我实现了TransferListener接口的onBytesSent(就像测试一样):

public void onBytesSent(ByteBuffer byteBuffer) {

     System.out.println("Total bytes sent - ");
     System.out.println(byteBuffer.capacity());
}

然后在另一个线程中(因为我不想阻止该应用程序)我尝试执行以下操作:

TransferCompletionHandler tl = new TransferCompletionHandler();
tl.addTransferListener(listener);

asyncHttpClient.preparePut(getFullUrl(fileWithPath))
      .setBody(new BodyGenerator() {
           public Body createBody() throws IOException {
                return new FileBodyWithOffset(file, offset);
           }
       })
       .addHeader(CONTENT_RANGE, new ContentRange(offset, localSize).toString())
       .execute(handler).get();

一切都很好。文件上传正确,速度非常快。但问题是 - 我在TransferListener中仅从onBytesSent收到消息 AFTER 上传完成。例如,上传在10分钟内完成。在那10分钟里,我一无所获。只有在那之后,一切都会打印在控制台上。

我无法弄清楚这段代码有什么问题。我只是试着按照文档进行操作。

我试图在主线程中执行上面的代码,但它也没有用。

使用此客户端实现上传进度监听器可能是错误的方法吗?

1 个答案:

答案 0 :(得分:2)

我会自己回答。我没有设法解决TransferListener的问题。所以我尝试了另一种方式。

我已将进度logick放在Body接口实现中(在read方法中):

public class FileBodyWithOffset implements Body {

    private final ReadableByteChannel channel;

    private long actualOffset;

    private final long contentLength;

    public FileBodyWithOffset(final File file, final long offset) throws IOException {

        final InputStream stream = new FileInputStream(file);

        this.actualOffset = stream.skip(offset);

        this.contentLength = file.length() - offset;

        this.channel = Channels.newChannel(stream);
    }


    public long getContentLength() {

        return this.contentLength;
    }

    public long read(ByteBuffer byteBuffer) throws IOException {

        System.out.println(new Date());

        actualOffset += byteBuffer.capacity();

        return channel.read(byteBuffer);
    }

    public void close() throws IOException {

        channel.close();
    }

    public long getActualOffset() {

        return actualOffset;
    }
}

也许这是一个肮脏的伎俩,但至少它是有效的。