Android – 我想向用户显示file upload进度

我通过Android SDK中的默认HttpClient将照片上传到服务器。 我想在用户界面上显示进度,有没有办法找出已经上传了多less? HttpUrlConnection有可能吗?

Related of "Android – 我想向用户显示file upload进度"

对我来说,HTTPClient不起作用。 刷新调用后,在部分缓冲区中发送的字节总数。 什么工作是发送它在套接字级别。

您可以使用HttpMultipartClient进行此操作(更新后的30-10-2011): http : //code.google.com/p/rainbowlibs/source/browse/android/trunk/rainbowlibs/src/it/rainbowbreeze/libs/数据/ HttpMultipartClient.java?规格= svn94&R = 94

指定每个零件的字节数量并更新while循环中的进度条:

while((line = reader.readLine())!= null &&!headersEnd)

按以下方式调用HttpMultipartClient:

HttpMultipartClient httpMultipartClient = new HttpMultipartClient("bluppr.com", "/api/order/create", 80); FileInputStream fis = new FileInputStream(path + fileName); httpMultipartClient.addFile(fileName, fis, fis.available()); httpMultipartClient.setRequestMethod("POST"); httpMultipartClient.send(); 

在服务器端使用:

 <?php $target_path = "uploads/"; $target_path = $target_path . basename( $_FILES['uploadedfile']['name']); if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file ". basename( $_FILES['uploadedfile']['name'])." has been uploaded " .$_POST["order"]. " post"; } else{ echo "There was an error uploading the file, please try again!"; } ?> 

我用这个Bluppr明信片,就像一个魅力。 如果你需要更多的信息,让我知道。

1)确保使用自己的线程在服务中执行上传。

2)获得进展:在这个类中包装你的InputStream,并且使用一个httpmime.jar库,它具有支持HttpClient的MultiPart。 我使用了一个线程来检查进度并更新通知中的进度条。

 package com.hyves.android.service.upload; import java.io.IOException; import java.io.InputStream; /** * This outputstream wraps an existing outputstream and provides * callbacks after certain amount of bytes to a HttpCallback * * @author tjerk */ public class ProgressNotifyingInputStream extends InputStream { private InputStream wrappedStream; private int count = 0; private int totalSize; /** * Creates a new notifying outputstream which wraps an existing one. * When you write to this stream the callback will be notified each time when * updateAfterNumberBytes is written. * * @param stream the outputstream to be wrapped * @param totalSize the totalsize that will get written to the stream */ public ProgressNotifyingInputStream(InputStream stream, int totalSize) { if(stream==null) { throw new NullPointerException(); } if(totalSize == 0) { throw new IllegalArgumentException("totalSize argument cannot be zero"); } this.wrappedStream = stream; this.totalSize = totalSize; } @Override public int read() throws IOException { count++; return wrappedStream.read(); } /** * Get progress from 0 to 100 * @return */ public int getProgress() { return count * 100 / totalSize; } } 

我需要一个图像的上传进度,并没有使用HttpMultipartClient,因为实现问题(通过gradle和依赖性错误获取包的麻烦)。 我遇到的另一个问题是获取想要上传的图像的实际文件大小。

我的要求还包括在通知区域进行上传。 这是我的解决scheme:

获取图像大小

 protected int sizeOf(Bitmap data) { /* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return data.getAllocationByteCount(); } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) { return data.getRowBytes() * data.getHeight(); } else { return data.getByteCount(); } // NONE OF THE ABOVE RETURN ACCURATE RESULTS! // A Bitmap, when stored as a file takes up more room because it represents // full pixel data and is not compressed on disk. */ byte[] bitmapdata = getBmpAsByteArray(data); return (bitmapdata == null) ? 0 : bitmapdata.length; } 

AsyncHttpPostTask extends AsyncTask<UploadableImage, Integer, String>

AsyncHttpPostTask#onProgressUpdate

这个函数在AsyncHttpPostTask#doInBackground中被调用,它调用callback来提醒状态改变的活动。

 @Override protected void onProgressUpdate(Integer... progress) { ((ImageUploadActivity) activity).updateProgress(progress[0]); } 

AsyncHttpPostTask#doInBackground

正如我之前提到的,我没有使用HttpMultipartClient ,所以我不得不自己去实现。 大部分来自http://www.androidsnippets.com/multipart-http-requests

 @Override protected String doInBackground(InputStream... inStream) { if (MainActivity.isDebugMode) { Log.d(TAG, "doInBackground"); } HttpURLConnection connection; DataOutputStream outputStream; InputStream inputStream; String twoHyphens = "--"; String boundary = "----------MobileFormData"; String lineEnd = "\r\n"; String result; int bytesRead, bytesAvailable, bufferSize; byte[] buffer; int maxBufferSize = 32768; // 2^15 = 32k -- http://stackoverflow.com/a/11221907/940217 try { InputStream is = inStream[0]; totalSize = curUpImage.getFileSize(); Log.e(TAG, "Determined the file size to be " + totalSize + " bytes"); URL url = new URL(this.server); connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setChunkedStreamingMode(maxBufferSize); connection.setRequestMethod("POST"); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0"); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); outputStream = new DataOutputStream(connection.getOutputStream()); // Upload POST Data Log.e(TAG, "Args: "+this.postArgs); String[] posts = this.postArgs.split("&"); for (String post : posts) { outputStream.writeBytes(twoHyphens + boundary + lineEnd); String[] kv = post.split("="); outputStream.writeBytes(String.format("Content-Disposition: form-data; name=\"%s\"", kv[0])); outputStream.writeBytes(lineEnd); outputStream.writeBytes(lineEnd); outputStream.writeBytes(String.format("%s", kv[1])); outputStream.writeBytes(lineEnd); } outputStream.writeBytes(twoHyphens + boundary + lineEnd); outputStream.writeBytes("Content-Disposition: form-data; name=\"" + this.fileParamConst + "\"; filename=\"image.jpg\"" + lineEnd); outputStream.writeBytes("Content-Type: image/jpeg" + lineEnd); outputStream.writeBytes(lineEnd); bytesAvailable = is.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); buffer = new byte[bufferSize]; int totalByteRead = 0; bytesRead = is.read(buffer, 0, bufferSize); while (bytesRead > 0) { totalByteRead += bytesRead; Log.w(TAG, "totalByteRead: "+totalByteRead+", totalSize: "+totalSize); publishProgress((int) ((totalByteRead / (float) totalSize) * 100)); outputStream.write(buffer, 0, bufferSize); bytesAvailable = is.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = is.read(buffer, 0, bufferSize); } if (totalByteRead == 0){ Log.e(TAG, "Total bytes read from image file: "+totalByteRead); } else { Log.d(TAG, "Total bytes read from image file: "+totalByteRead); } outputStream.writeBytes(lineEnd); outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); inputStream = connection.getInputStream(); result = this.convertStreamToString(inputStream); is.close(); inputStream.close(); outputStream.flush(); outputStream.close(); return result; } catch (MalformedURLException e) { result = "Error - Malformed URL"; e.printStackTrace(); } catch (FileNotFoundException e) { result = "Error - Image file not found."; e.printStackTrace(); } catch (IOException e) { result = "Error - IO Exception."; e.printStackTrace(); } return result; } 

AsyncHttpPostTask#onPostExecute

在这里,我parsing我的服务器的JSON响应,看看上传是否能够成功处理,然后返回一个消息到控制通知的活动。

 @Override protected void onPostExecute(String result) { String resultString = null; if (MainActivity.isDebugMode){ Log.d(TAG, "Async result: "+result); } boolean successful = false; String[] errorMessages = null; try { JSONObject mainObject = new JSONObject(result); String resultJsonString = mainObject.getString("result"); JSONArray messagesJsonArray = mainObject.getJSONArray("messages"); if (resultJsonString != null){ if (resultJsonString.equalsIgnoreCase("success")){ successful = true; } else { Log.e(TAG, "result was: "+resultJsonString); } } errorMessages = new String[messagesJsonArray.length()]; for (int i = 0; i < messagesJsonArray.length(); i++){ errorMessages[i]= (String)messagesJsonArray.get(i); } } catch (JSONException e){ Log.e(TAG, "JSON Exception -- The string that I tried to parse was:\n"+result); e.printStackTrace(); } if (successful) { Toast.makeText(this.activity, "Upload completed successfully!", Toast.LENGTH_SHORT).show(); resultString = "Upload complete."; } else { String eMessages; if (errorMessages != null && errorMessages.length > 0){ eMessages = TextUtils.join(", ", errorMessages); resultString = "Image upload failed:\n"+eMessages; } else { resultString = "Image upload failed!"; } } ((ImageUploadActivity) activity).updateProgress(null); ((ImageUploadActivity) activity).setPostResult(resultString); } 

显示进度

在负责通知的Activity中,我有这个从asynchronous任务调用的callback函数。 在这里显示的进展也可以使用John Russell的博客文章中讨论的解决scheme之一来完成。 此活动以singleTop模式启动,以便在通知被带到前面时,状态将被保留。

ImageUploadActivity#buildNotify

 private void buildNotify(){ Intent resultIntent = new Intent(this, ImageUploadActivity.class); // Because clicking the notification opens a new ("special") activity, there's // no need to create an artificial back stack. PendingIntent resultPendingIntent = PendingIntent.getActivity( this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT ); mNotifyManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new NotificationCompat.Builder(this); mBuilder.setContentIntent(resultPendingIntent); mBuilder.setContentTitle("Image Upload") .setContentText("Image upload in progress") .setSmallIcon(android.R.drawable.ic_menu_upload); } 

ImageUploadActivity#的UpdateProgress

此方法将刷新通知的进度以及Activity中包含的UI。

 public void updateProgress(Integer progress){ this.currentProgress = progress; if (uploadStatusTV != null && this.currentProgress != null){ currentStatus = "uploading image: "+this.currentProgress+"%"; uploadStatusTV.setText("uploading image: "+this.currentProgress+"%"); if (mBuilder == null){ buildNotify(); } // Sets the progress indicator to a max value, the // current completion percentage, and "determinate" state mBuilder.setProgress(100, currentProgress, false); // Displays the progress bar for the first time. mNotifyManager.notify(notify_id, mBuilder.build()); } else if (uploadStatusTV != null){ return; } else { Log.e(TAG, "You should never see this message."); finish(); } } 

或者你应该使用AsyncTask来完成file upload的实际过程,并使用ProcessDialog来启动和停止进程。

你可以看到这个代码,我写的http://github.com/narup/mymobile/blob/master/pbdroid/src/com/example/android/skeletonapp/StoreListActivity.java通过HTTP加载JSON数据,我使用过程对话&#x3002;

代码的主要部分是:

  private class LoadStoresTask extends AsyncTask<String, Void, List<Store>> { @Override protected List<Store> doInBackground(String... params) { return WsiStoresClient.connect(params[0]); } @Override protected void onPostExecute(List<Store> result) { dismissDialog(BUSY_DIALOG_KEY); } } 

我写了一个如何做到这一点的例子 – > http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/

我没有使用该API,但注意到HttpClient不是特定于Android的:

 org.apache.http.client.HttpClient 

所以如果你谷歌的“HttpClient进展”有一些可能是有用的职位。

另外,请考虑发布Android下载进度

我没有使用httpclient,但我做了像你想使用AsyncTask东西。

  private class DownloadImageTask extends AsyncTask<String, Void,Bitmap>{ protected Bitmap doInBackground(String... urls) { while (myProgress<length){ myProgress=myProgress+1; myProgressBar.setProgress(myProgress); } return decodeImage(urls[0]); } protected void onPostExecute(Bitmap result) { //dialog.dismiss(); imView.setImageBitmap(result); } protected void onPreExecute() { /* Things to be done while execution of long running operation is in progress. For example updating ProgressDialog */ dialog = ProgressDialog.show(BusinessCardActivity.this, "Loading.........","Wait For Few Second", true); } } 

请参阅后台进程我正在增加进度条和解码图像,并在后期执行我设置图像。