具有进度栏的MultipartEntityBuilder [英] MultipartEntityBuilder with progressbar
问题描述
我正在使用以下代码通过MultipartEntityBuilder将照片上传到我的服务器.最后某处显示// FIXME Put your progress bar stuff here!
.我不知道是否应该将整个功能放在Asynctask中,或者在上传文件时应该如何显示进度.
I am using the following code to upload a photo to my server with MultipartEntityBuilder. Somewhere at the end it says // FIXME Put your progress bar stuff here!
. I don't know if I should put the whole function into an Asynctask or what I should do to display progress while the file is uploaded.
我检查了上传文件通过HTTP表单,通过MultipartEntityBuilder并带有进度条,但这并没有真正的帮助.
I checked Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar but it doesn't really help.
public String postFile(String fileName) throws Exception {
fileName = "/mnt/sdcard/DCIM/100MEDIA/IMAG0309.jpg";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.mywebsite.com/upload_file.php");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
final File file = new File(fileName);
FileBody fb = new FileBody(file);
builder.addPart("file",fb);
String userid = session_userid;
builder.addTextBody("userID", userid);
final HttpEntity yourEntity = builder.build();
class ProgressiveEntity implements HttpEntity {
@Override
public void consumeContent() throws IOException {
yourEntity.consumeContent();
}
@Override
public InputStream getContent() throws IOException,
IllegalStateException {
return yourEntity.getContent();
}
@Override
public Header getContentEncoding() {
return yourEntity.getContentEncoding();
}
@Override
public long getContentLength() {
return yourEntity.getContentLength();
}
@Override
public Header getContentType() {
return yourEntity.getContentType();
}
@Override
public boolean isChunked() {
return yourEntity.isChunked();
}
@Override
public boolean isRepeatable() {
return yourEntity.isRepeatable();
}
@Override
public boolean isStreaming() {
return yourEntity.isStreaming();
} // CONSIDER put a _real_ delegator into here!
@Override
public void writeTo(OutputStream outstream) throws IOException {
class ProxyOutputStream extends FilterOutputStream {
public ProxyOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(int idx) throws IOException {
out.write(idx);
}
public void write(byte[] bts) throws IOException {
out.write(bts);
}
public void write(byte[] bts, int st, int end) throws IOException {
out.write(bts, st, end);
}
public void flush() throws IOException {
out.flush();
}
public void close() throws IOException {
out.close();
}
}
class ProgressiveOutputStream extends ProxyOutputStream {
int totalSent;
public ProgressiveOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(byte[] bts, int st, int end) throws IOException {
// FIXME Put your progress bar stuff here!
out.write(bts, st, end);
}
}
yourEntity.writeTo(new ProgressiveOutputStream(outstream));
}
};
ProgressiveEntity myEntity = new ProgressiveEntity();
post.setEntity(myEntity);
HttpResponse response = client.execute(post);
return getContent(response);
}
这是我所做的,但是我仍然需要你们来完成它:
Here is what I did but I still need you guys for finishing it:
@Override
protected String doInBackground(HttpResponse... arg0)
{
String fileName = "/mnt/sdcard/DCIM/100MEDIA/IMAG0309.jpg";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.mywebsite.com/upload_file.php");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
final File file = new File(fileName);
FileBody fb = new FileBody(file);
builder.addPart("file",fb);
String userid = session_userid;
builder.addTextBody("userID", userid);
final HttpEntity yourEntity = builder.build();
class ProgressiveEntity implements HttpEntity {
@Override
public void consumeContent() throws IOException {
yourEntity.consumeContent();
}
@Override
public InputStream getContent() throws IOException,
IllegalStateException {
return yourEntity.getContent();
}
@Override
public Header getContentEncoding() {
return yourEntity.getContentEncoding();
}
@Override
public long getContentLength() {
return yourEntity.getContentLength();
}
@Override
public Header getContentType() {
return yourEntity.getContentType();
}
@Override
public boolean isChunked() {
return yourEntity.isChunked();
}
@Override
public boolean isRepeatable() {
return yourEntity.isRepeatable();
}
@Override
public boolean isStreaming() {
return yourEntity.isStreaming();
} // CONSIDER put a _real_ delegator into here!
@Override
public void writeTo(OutputStream outstream) throws IOException {
class ProxyOutputStream extends FilterOutputStream {
public ProxyOutputStream(OutputStream proxy) {
super(proxy);
}
public void write(int idx) throws IOException {
out.write(idx);
}
public void write(byte[] bts) throws IOException {
out.write(bts);
}
public void write(byte[] bts, int st, int end) throws IOException {
out.write(bts, st, end);
}
public void flush() throws IOException {
out.flush();
}
public void close() throws IOException {
out.close();
}
}
class ProgressiveOutputStream extends ProxyOutputStream {
public ProgressiveOutputStream(OutputStream proxy) {
super(proxy);
int totalSent = 0;
}
public void write(byte[] bts, int st, int end) throws IOException {
// FIXME Put your progress bar stuff here!
//what's totalSize?
publishProgress((int) ((end / (float) totalSize) * 100));
out.write(bts, st, end);
}
}
yourEntity.writeTo(new ProgressiveOutputStream(outstream));
}
};
ProgressiveEntity myEntity = new ProgressiveEntity();
post.setEntity(myEntity);
HttpResponse response = client.execute(post);
return getContent(response);
//Here it says I should put this into a try catch but then I get an error on
// the doInBackground line saying it needs to return a string
}
protected void onProgressUpdate(Integer... progress) {
pd.setProgress((int) (progress[0]));
}
@SuppressWarnings("deprecation")
@Override
protected void onPostExecute(String file_url) {
pd.dismiss();
connection.disconnect();
Toast.makeText(getApplicationContext(), "Ready.", Toast.LENGTH_LONG).show();
}
}
推荐答案
我正在尝试实现类似的目的(我使用ProgressDialog
而不是ProgressBar
).您必须使用AsyncTask
,以便主线程不会等待上传完成(上传必须是异步的).
I was trying to achieve something similar (I use ProgressDialog
instead of ProgressBar
). You have to use AsyncTask
so the main thread won't be waiting for your upload to finish (Upload must be asynchronous).
Create a extension for
HttpEntityWrapped
(credits: here):
public class MyHttpEntity extends HttpEntityWrapper {
private ProgressListener progressListener;
public MyHttpEntity(final HttpEntity entity, final ProgressListener progressListener) {
super(entity);
this.progressListener = progressListener;
}
@Override
public void writeTo(OutputStream outStream) throws IOException {
this.wrappedEntity.writeTo(outStream instanceof ProgressOutputStream ? outStream :
new ProgressOutputStream(outStream, this.progressListener,
this.getContentLength()));
}
public static interface ProgressListener {
void transferred(float progress);
}
public static class ProgressOutputStream extends FilterOutputStream {
private final ProgressListener progressListener;
private long transferred;
private long total;
public ProgressOutputStream(final OutputStream outputStream,
final ProgressListener progressListener,
long total) {
super(outputStream);
this.progressListener = progressListener;
this.transferred = 0;
this.total = total;
}
@Override
public void write(byte[] buffer, int offset, int length) throws IOException {
out.write(buffer, offset, length);
this.transferred += length;
this.progressListener.transferred(this._getCurrentProgress());
}
@Override
public void write(byte[] buffer) throws IOException {
out.write(buffer);
this.transferred++;
this.progressListener.transferred(this._getCurrentProgress());
}
private float _getCurrentProgress() {
return ((float) this.transferred / this.total) * 100;
}
}
}
我创建了在Activity
中扩展AsyncTask
的私有类.在doInBackground
中,使用MultipartEntityBuilder
添加文件和所需的任何内容.如果上传成功(代码== 200,这是我的自定义json响应),则会调用onPostExecute
.
I've created private class that extends AsyncTask
in an Activity
. In doInBackground
you use MultipartEntityBuilder
to add your file and anything you want. If upload is successful (code == 200, it's my custom json response), onPostExecute
will be called.
私有类UploadAsyncTask扩展了AsyncTask {
private class UploadAsyncTask extends AsyncTask {
private Context context;
private Exception exception;
private ProgressDialog progressDialog;
private UploadAsyncTask(Context context) {
this.context = context;
}
@Override
protected Boolean doInBackground(String... params) {
String uploadUrl = URL + "upload";
HttpResponse response = null;
try {
HttpPost post = new HttpPost(uploadUrl);
// Entity
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
// Add your file
multipartEntityBuilder.addPart("file", new FileBody(new File(params[0])));
// Progress listener - updates task's progress
MyHttpEntity.ProgressListener progressListener =
new MyHttpEntity.ProgressListener() {
@Override
public void transferred(float progress) {
UploadAsyncTask.this.publishProgress((int) progress);
}
};
// POST
post.setEntity(new MyHttpEntity(multipartEntityBuilder.build(),
progressListener));
// Handle response
GsonBuilder builder = new GsonBuilder();
LinkedTreeMap object = builder.create().fromJson(
EntityUtils.toString(client.execute(post).getEntity()),
LinkedTreeMap.class);
if ((double) object.get("code") == 200.0) {
return true;
}
} catch (UnsupportedEncodingException | JsonSyntaxException | ClientProtocolException e) {
e.printStackTrace();
Log.e("UPLOAD", e.getMessage());
this.exception = e;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
protected void onPreExecute() {
// Init and show dialog
this.progressDialog = new ProgressDialog(this.context);
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.progressDialog.show();
}
@Override
protected void onPostExecute(Boolean result) {
// Close dialog
this.progressDialog.dismiss();
if (result) {
Toast.makeText(getApplicationContext(),
R.string.upload_success, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
R.string.upload_failure, Toast.LENGTH_LONG).show();
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
// Update process
this.progressDialog.setProgress((int) progress[0]);
}
}
在Acitvity
内的呼叫上传:
private void _upload(){
private void _upload() {
UploadAsyncTask task = new UploadAsyncTask(this);
task.execute();
}
这篇关于具有进度栏的MultipartEntityBuilder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!