接上一篇文章《Android上传文件到Web服务器,PHP接收文件(一)》,这次在之前的基础上添加进度显示,Java代码如下所示:
- package com.lenovo.uptest;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.ProgressDialog;
- import android.content.DialogInterface;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- public class UploadtestActivity extends Activity {
- /** Called when the activity is first created. */
- /**
- * Upload file to web server with progress status, client: android;
- * server:php
- * **/
- private TextView mtv1 = null;
- private TextView mtv2 = null;
- private Button bupload = null;
- private String uploadFile = "/sdcard/testimg.jpg";
- private String actionUrl = "http://10.100.1.208/receive_file.php";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mtv1 = (TextView) findViewById(R.id.mtv1);
- mtv1.setText("文件路径:\n" + uploadFile);
- mtv2 = (TextView) findViewById(R.id.mtv2);
- mtv2.setText("上传地址:\n" + actionUrl);
- bupload = (Button) findViewById(R.id.bupload);
- bupload.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- FileUploadTask fileuploadtask = new FileUploadTask();
- fileuploadtask.execute();
- }
- });
- }
- // show Dialog method
- private void showDialog(String mess) {
- new AlertDialog.Builder(UploadtestActivity.this).setTitle("Message")
- .setMessage(mess)
- .setNegativeButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- }).show();
- }
- class FileUploadTask extends AsyncTask<Object, Integer, Void> {
- private ProgressDialog dialog = null;
- HttpURLConnection connection = null;
- DataOutputStream outputStream = null;
- DataInputStream inputStream = null;
- //the file path to upload
- String pathToOurFile = "/sdcard/testimg.jpg";
- //the server address to process uploaded file
- String urlServer = "http://10.100.1.208/receive_file.php";
- String lineEnd = "\r\n";
- String twoHyphens = "--";
- String boundary = "*****";
- File uploadFile = new File(pathToOurFile);
- long totalSize = uploadFile.length(); // Get size of file, bytes
- @Override
- protected void onPreExecute() {
- dialog = new ProgressDialog(UploadtestActivity.this);
- dialog.setMessage("正在上传...");
- dialog.setIndeterminate(false);
- dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- dialog.setProgress(0);
- dialog.show();
- }
- @Override
- protected Void doInBackground(Object... arg0) {
- long length = 0;
- int progress;
- int bytesRead, bytesAvailable, bufferSize;
- byte[] buffer;
- int maxBufferSize = 256 * 1024;// 256KB
- try {
- FileInputStream fileInputStream = new FileInputStream(new File(
- pathToOurFile));
- URL url = new URL(urlServer);
- connection = (HttpURLConnection) url.openConnection();
- // Set size of every block for post
- connection.setChunkedStreamingMode(256 * 1024);// 256KB
- // Allow Inputs & Outputs
- connection.setDoInput(true);
- connection.setDoOutput(true);
- connection.setUseCaches(false);
- // Enable POST method
- connection.setRequestMethod("POST");
- connection.setRequestProperty("Connection", "Keep-Alive");
- connection.setRequestProperty("Charset", "UTF-8");
- connection.setRequestProperty("Content-Type",
- "multipart/form-data;boundary=" + boundary);
- outputStream = new DataOutputStream(
- connection.getOutputStream());
- outputStream.writeBytes(twoHyphens + boundary + lineEnd);
- outputStream
- .writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
- + pathToOurFile + "\"" + lineEnd);
- outputStream.writeBytes(lineEnd);
- bytesAvailable = fileInputStream.available();
- bufferSize = Math.min(bytesAvailable, maxBufferSize);
- buffer = new byte[bufferSize];
- // Read file
- bytesRead = fileInputStream.read(buffer, 0, bufferSize);
- while (bytesRead > 0) {
- outputStream.write(buffer, 0, bufferSize);
- length += bufferSize;
- progress = (int) ((length * 100) / totalSize);
- publishProgress(progress);
- bytesAvailable = fileInputStream.available();
- bufferSize = Math.min(bytesAvailable, maxBufferSize);
- bytesRead = fileInputStream.read(buffer, 0, bufferSize);
- }
- outputStream.writeBytes(lineEnd);
- outputStream.writeBytes(twoHyphens + boundary + twoHyphens
- + lineEnd);
- publishProgress(100);
- // Responses from the server (code and message)
- int serverResponseCode = connection.getResponseCode();
- String serverResponseMessage = connection.getResponseMessage();
- /* 将Response显示于Dialog */
- // Toast toast = Toast.makeText(UploadtestActivity.this, ""
- // + serverResponseMessage.toString().trim(),
- // Toast.LENGTH_LONG);
- // showDialog(serverResponseMessage.toString().trim());
- /* 取得Response内容 */
- // InputStream is = connection.getInputStream();
- // int ch;
- // StringBuffer sbf = new StringBuffer();
- // while ((ch = is.read()) != -1) {
- // sbf.append((char) ch);
- // }
- //
- // showDialog(sbf.toString().trim());
- fileInputStream.close();
- outputStream.flush();
- outputStream.close();
- } catch (Exception ex) {
- // Exception handling
- // showDialog("" + ex);
- // Toast toast = Toast.makeText(UploadtestActivity.this, "" +
- // ex,
- // Toast.LENGTH_LONG);
- }
- return null;
- }
- @Override
- protected void onProgressUpdate(Integer... progress) {
- dialog.setProgress(progress[0]);
- }
- @Override
- protected void onPostExecute(Void result) {
- try {
- dialog.dismiss();
- // TODO Auto-generated method stub
- } catch (Exception e) {
- }
- }
- }
- }
服务器端仍然和之前的一样。
这里使用了AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单,适用于简单的异步处理,不需要借助线程和Handler即可实现。
AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
1) 子类化AsyncTask
2) 实现AsyncTask中定义的下面一个或几个方法
onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第三个为doInBackground返回和onPostExecute传入的参数。
运行结果如下: