我对Java 非常陌生,并且大部分时间都在教我自己,所以我开始构建一个applet.我想创建一个可以从本地磁盘中选择文件并将其作为multipart/form-data POST请求上传但有进度条的文件.显然,用户必须授予Java applet访问硬盘驱动器的权限.现在我已经完成了第一部分工作:用户可以使用JFileChooser
对象选择一个文件,方便地返回一个File
对象.但我想知道接下来会发生什么.我知道这File.length()
将给我文件的总大小(以字节为单位),但是如何将所选内容发送File
到网络,以及如何监控已发送的字节数?提前致谢.
要使用HttpClient检查进度,请将MultipartRequestEntity包装在计算发送字节数的周围.包装如下:
import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.httpclient.methods.RequestEntity; public class CountingMultipartRequestEntity implements RequestEntity { private final RequestEntity delegate; private final ProgressListener listener; public CountingMultipartRequestEntity(final RequestEntity entity, final ProgressListener listener) { super(); this.delegate = entity; this.listener = listener; } public long getContentLength() { return this.delegate.getContentLength(); } public String getContentType() { return this.delegate.getContentType(); } public boolean isRepeatable() { return this.delegate.isRepeatable(); } public void writeRequest(final OutputStream out) throws IOException { this.delegate.writeRequest(new CountingOutputStream(out, this.listener)); } public static interface ProgressListener { void transferred(long num); } public static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; public CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } public void write(int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } }
然后实现一个更新进度条的ProgressListener.
请记住,进度条更新不得在Event Dispatch Thread上运行.
更简单的countEntity不依赖于特定的实体类型,而是扩展HttpEntityWrapped
:
package gr.phaistos.android.util; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.http.HttpEntity; import org.apache.http.entity.HttpEntityWrapper; public class CountingHttpEntity extends HttpEntityWrapper { public static interface ProgressListener { void transferred(long transferedBytes); } static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } @Override public void write(final byte[] b, final int off, final int len) throws IOException { //// NO, double-counting, as super.write(byte[], int, int) delegates to write(int). //super.write(b, off, len); out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } @Override public void write(final int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } private final ProgressListener listener; public CountingHttpEntity(final HttpEntity entity, final ProgressListener listener) { super(entity); this.listener = listener; } @Override public void writeTo(final OutputStream out) throws IOException { this.wrappedEntity.writeTo(out instanceof CountingOutputStream? out: new CountingOutputStream(out, this.listener)); } }
我最终绊倒了一个开源Java上传器小程序,并在其代码中找到了我需要知道的一切.以下是描述它的博客文章的链接以及来源:
文章
源代码
侦听器返回的字节数与原始文件大小不同.所以,transferred++
我没有修改,而是修改它transferred=len
; 这是写入输出流的实际字节数的长度.当我计算添加的总字节数时,它等于ContentLength
返回的实际值CountingMultiPartEntity.this.getContentLength();
public void write(byte[] b, int off, int len) throws IOException { wrappedOutputStream_.write(b,off,len); transferred=len; listener_.transferred(transferred); }