实现HttpClient上传文件进度条

来源:互联网 发布:网络零售可以有哪些 编辑:程序博客网 时间:2024/05/17 01:41
我有下面的代码为一个文件上传与Apache的HTTP的客户端端(org.apache.http.client):
 public static void main(String[] args) throws Exception { String fileName = "test.avi"; File file = new File(fileName); String serverResponse = null; HttpParams params = new BasicHttpParams(); params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, true); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpClient client = new DefaultHttpClient(params); HttpPut put = new HttpPut(" CodeGo.net  + fileName); FileEntity fileEntity = new FileEntity(file, "binary/octet-stream"); put.setEntity(fileEntity);  HttpResponse response = client.execute(put); HttpEntity entity = response.getEntity(); if (entity != null) {  serverResponse = EntityUtils.toString(entity);  System.out.println(serverResponse); } }
它工作的很好,但现在我想有一个进度条,显示文件上传进度。这怎么可能呢?我发现了一个代码片段的文件上传与Java(带进度条),但它是专为Apache的HTTP客户端端3(org.和RequestEntity类没有在Apache的HTTP客户端端4存在;。( 也许你有办法? 许多问候 班尼
本文地址 :CodeGo.net/341712/ 
------------------------------------------------------------------------------------------------------------------------- 
1. 我介绍一个派生FileEntity只是计数写入的字节。OutputStreamProgress做了实际的计数(一种decorator器的实际OutputStream)。 这样做的好处(与装修一般)是,我不需要从文件流复制的实际就像实际的复制到输出流。我也可以改变一个不同的(新)之类的NFileEntity。 享受... FileEntity.java
public class FileEntity extends org.apache.http.entity.FileEntity { private OutputStreamProgress outstream; public FileEntity(File file, String contentType) {  super(file, contentType); } @Override public void writeTo(OutputStream outstream) throws IOException {  this.outstream = new OutputStreamProgress(outstream);  super.writeTo(this.outstream); } /**  * Progress: 0-100  */ public int getProgress() {  if (outstream == null) {   return 0;  }  long contentLength = getContentLength();  if (contentLength <= 0) { // Prevent division by zero and negative values   return 0;  }  long writtenLength = outstream.getWrittenLength();  return (int) (100*writtenLength/contentLength); }}
OutputStreamProgress.java
public class OutputStreamProgress extends OutputStream { private final OutputStream outstream; private volatile long bytesWritten=0; public OutputStreamProgress(OutputStream outstream) {  this.outstream = outstream; } @Override public void write(int b) throws IOException {  outstream.write(b);  bytesWritten++; } @Override public void write(byte[] b) throws IOException {  outstream.write(b);  bytesWritten += b.length; } @Override public void write(byte[] b, int off, int len) throws IOException {  outstream.write(b, off, len);  bytesWritten += len; } @Override public void flush() throws IOException {  outstream.flush(); } @Override public void close() throws IOException {  outstream.close(); } public long getWrittenLength() {  return bytesWritten; }}

2. 这个答案通过添加一个简单的监听器OutputStreamProgress.java类,而不是由公众getProgress()方法(我真的不知道你是如何想调用getProgress()方法,因为该线程会执行内部延伸kilaka的回答的HttpClient的代码,整个你可能需要调用getProgress()!)。 请注意,您需要延长您希望每个实体类型的实体类,当你写你的HttpClient代码 CodeGo.net,你需要创建一个新的类型的实体。 我写了一个非常基本的写听者的WriteListener接口。在这里,您将添加你的逻辑做从OutputStreamProgress写报告,如更新一个进度条:) 非常感谢kilakadecorator理念在点票outstream潜行。 WriteLisener.java
public interface WriteListener { void registerWrite(long amountOfBytesWritten);}
OutputStreamProgress.java
import java.io.IOException;import java.io.OutputStream;public class OutputStreamProgress extends OutputStream { private final OutputStream outstream; private long bytesWritten=0; private final WriteListener writeListener; public OutputStreamProgress(OutputStream outstream, WriteListener writeListener) {  this.outstream = outstream;  this.writeListener = writeListener; } @Override public void write(int b) throws IOException {  outstream.write(b);  bytesWritten++;  writeListener.registerWrite(bytesWritten); } @Override public void write(byte[] b) throws IOException {  outstream.write(b);  bytesWritten += b.length;  writeListener.registerWrite(bytesWritten); } @Override public void write(byte[] b, int off, int len) throws IOException {  outstream.write(b, off, len);  bytesWritten += len;  writeListener.registerWrite(bytesWritten); } @Override public void flush() throws IOException {  outstream.flush(); } @Override public void close() throws IOException {  outstream.close(); }}
BasicWriteListener
public class BasicWriteListener implements WriteListener {public BasicWriteListener() { // TODO Auto-generated constructor stub}public void registerWrite(long amountOfBytesWritten) { System.out.println(amountOfBytesWritten);}}
MultipartEntityWithProgressBar
import java.io.IOException;import java.io.OutputStream;import java.nio.charset.Charset;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntity;public class MultipartEntityWithProgressBar extends MultipartEntity { private OutputStreamProgress outstream; private WriteListener writeListener; @Override public void writeTo(OutputStream outstream) throws IOException {  this.outstream = new OutputStreamProgress(outstream, writeListener);  super.writeTo(this.outstream); } public MultipartEntityWithProgressBar(WriteListener writeListener) {  super();  this.writeListener = writeListener; } public MultipartEntityWithProgressBar(HttpMultipartMode mode, WriteListener writeListener) {  super(mode);  this.writeListener = writeListener; } public MultipartEntityWithProgressBar(HttpMultipartMode mode, String boundary, Charset charset, WriteListener writeListener) {  super(mode, boundary, charset);  this.writeListener = writeListener; } // Left in for clarity to show where I took from kilaka's answer// /**// * Progress: 0-100// */// public int getProgress() {//  if (outstream == null) {//   return 0;//  }//  long contentLength = getContentLength();//  if (contentLength <= 0) { // Prevent division by zero and negative values//   return 0;//  }//  long writtenLength = outstream.getWrittenLength();//  return (int) (100*writtenLength/contentLength);// }}

3. 一个新的包组织结构。从公地-10(2.4)和它的类CountingOutputStream。 我改变了最初的代码,以反映我的项目需要一个多表单输入,(这个会费的征收服务器端)。 想想看,大文件的增量在我的测试中对应于4096个字节。该counterChanged()被调用传输的数据的每4096字节,什么是可以接受的情况。 看起来像:
public void post(String url, File sendFile) { HttpParams params = new BasicHttpParams(); params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, true); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpClient client = new DefaultHttpClient(params); HttpPost post = new HttpPost(url + "/" + sendFile.getName()); MultipartEntity multiEntity = new MultipartEntity();  MyFileBody fileBody = new MyFileBody(sendFile); fileBody.setListener(new IStreamListener(){  @Override  public void counterChanged(int delta) {   // do something   System.out.println(delta);  }}); multiEntity.addPart("file", fileBody); StringBody stringBody = new StringBody(sendFile.getName()); multiEntity.addPart("fileName", stringBody); post.setEntity(multiEntity);  HttpResponse response = client.execute(post);}
类MyFileBody
public class MyFileBody extends FileBody { private IStreamListener listener; public MyFileBody(File file) {  super(file); } @Override public void writeTo(OutputStream out) throws IOException {  CountingOutputStream output = new CountingOutputStream(out) {   @Override   protected void beforeWrite(int n) {    if (listener != null && n != 0)     listener.counterChanged(n);    super.beforeWrite(n);   }  };  super.writeTo(output); } public void setListener(IStreamListener listener) {  this.listener = listener; } public IStreamListener getListener() {  return listener; }}
最后,监听器接口的样子:
public interface IStreamListener { void counterChanged(int delta);}

4. 好家伙! 我解决了自己的问题,并做了一个简单的例子吧。 如果有任何问题,请随时提出。 在这里,我们走! ApplicationView.java
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.File;import java.util.logging.Level;import java.util.logging.Logger;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JProgressBar;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpVersion;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPut;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpParams;import org.apache.http.params.HttpProtocolParams;import org.apache.http.util.EntityUtils;public class ApplicationView implements ActionListener{ File file = new File("C:/Temp/my-upload.avi"); JProgressBar progressBar = null; public ApplicationView() { super(); } public void createView() { JFrame frame = new JFrame("File Upload with progress bar - Example"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(0, 0, 300, 200); frame.setVisible(true); progressBar = new JProgressBar(0, 100); progressBar.setBounds(20, 20, 200, 30); progressBar.setStringPainted(true); progressBar.setVisible(true); JButton button = new JButton("upload"); button.setBounds(progressBar.getX(),   progressBar.getY() + progressBar.getHeight() + 20,   100,   40); button.addActionListener(this); JPanel panel = (JPanel) frame.getContentPane(); panel.setLayout(null); panel.add(progressBar); panel.add(button); panel.setVisible(true); } public void actionPerformed(ActionEvent e) { try {  sendFile(this.file, this.progressBar); } catch (Exception ex) {  System.out.println(ex.getLocalizedMessage()); } } private void sendFile(File file, JProgressBar progressBar) throws Exception { String serverResponse = null; HttpParams params = new BasicHttpParams(); params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, true); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpClient client = new DefaultHttpClient(params); HttpPut put = new HttpPut(" CodeGo.net  + file.getName()); ProgressBarListener listener = new ProgressBarListener(progressBar); FileEntityWithProgressBar fileEntity = new FileEntityWithProgressBar(file, "binary/octet-stream", listener); put.setEntity(fileEntity); HttpResponse response = client.execute(put); HttpEntity entity = response.getEntity(); if (entity != null) {  serverResponse = EntityUtils.toString(entity);  System.out.println(serverResponse); } }}
FileEntityWithProgressBar.java
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import org.apache.http.entity.AbstractHttpEntity;/** * File entity which supports a progress bar.<br/> * Based on "org.apache.http.entity.FileEntity". * @author Benny Neugebauer ( CodeGo.net  */public class FileEntityWithProgressBar extends AbstractHttpEntity implements Cloneable{ protected final File file; private final ProgressBarListener listener; private long transferredBytes; public FileEntityWithProgressBar(final File file, final String contentType, ProgressBarListener listener) { super(); if (file == null) {  throw new IllegalArgumentException("File may not be null"); } this.file = file; this.listener = listener; this.transferredBytes = 0; setContentType(contentType); } public boolean isRepeatable() { return true; } public long getContentLength() { return this.file.length(); } public InputStream getContent() throws IOException { return new FileInputStream(this.file); } public void writeTo(final OutputStream outstream) throws IOException { if (outstream == null) {  throw new IllegalArgumentException("Output stream may not be null"); } InputStream instream = new FileInputStream(this.file); try {  byte[] tmp = new byte[4096];  int l;  while ((l = instream.read(tmp)) != -1)  {  outstream.write(tmp, 0, l);  this.transferredBytes += l;  this.listener.updateTransferred(this.transferredBytes);  }  outstream.flush(); } finally {  instream.close(); } } public boolean isStreaming() { return false; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }}
ProgressBarListener.java
import javax.swing.JProgressBar;public class ProgressBarListener{ private int transferedMegaBytes = 0; private JProgressBar progressBar = null; public ProgressBarListener() { super(); } public ProgressBarListener(JProgressBar progressBar) { this(); this.progressBar = progressBar; } public void updateTransferred(long transferedBytes) { transferedMegaBytes = (int) (transferedBytes / 1048576); this.progressBar.setValue(transferedMegaBytes); this.progressBar.paint(progressBar.getGraphics()); System.out.println("Transferred: " + transferedMegaBytes + " Megabytes."); }}
快乐编码! 
5. mmhh。无论工作在服务器总是返回IO错误:CRC校验失败=位于0x8! ->似乎破坏了流

本文标题 :如何获得一个文件的上传与Apache HttpClient的4进度条?
本文地址 :CodeGo.net/341712/ 
0 0
原创粉丝点击