如何在Android中实现文件上传进度条

14

我正在使用Android中的org.apache.http.client.HttpClient上传文件,并且需要实现进度条。是否可以从以下方式获取进度?

HttpPost httppost = new HttpPost("some path");
HttpClient httpclient = new DefaultHttpClient();
try {
File file = new File("file path");
InputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] bArray = new byte[(int) file.length()];
in.read(bArray);
String entity = Base64.encodeToString(bArray, Base64.DEFAULT);
httppost.setEntity(new StringEntity(entity));
HttpResponse response = httpclient.execute(httppost);
}

如果没有的话,请展示一种替代方式。谢谢。


2
这篇文章可能是你正在寻找的:Java文件上传带进度条 - Ovidiu Latcu
2个回答

22
你需要做的是创建一个 AsyncTast,可以使用 onProgressUpdate 方法来处理上传文件。以下是我在另一个应用程序中使用 HttpURLConnection 测试过的内容。该代码可能有一些冗余,并且 HttpURLConnection 可能不太被推荐使用,但这段代码应该可以工作。只需在你正在使用的 Activity 类中使用此类(在这个示例中,我将其称为 TheActivity),通过调用 new FileUploadTask().execute() 来执行。当然,你可能需要根据你的应用程序需要进行微调。
private class FileUploadTask extends AsyncTask<Object, Integer, Void> {

    private ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(TheActivity.this);
        dialog.setMessage("Uploading...");
        dialog.setIndeterminate(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setProgress(0);
        dialog.show();
    }

    @Override
    protected Void doInBackground(Object... arg0) {
        try {
            File file = new File("file path");
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fileInputStream.read(bytes);
            fileInputStream.close();

            URL url = new URL("some path");
            HttpURLConnection connection = 
                    (HttpURLConnection) url.openConnection();
            OutputStream outputStream = connection.getOutputStream();

            int bufferLength = 1024;
            for (int i = 0; i < bytes.length; i += bufferLength) {
                int progress = (int)((i / (float) bytes.length) * 100);
                publishProgress(progress);
                if (bytes.length - i >= bufferLength) {
                    outputStream.write(bytes, i, bufferLength);
                } else {
                    outputStream.write(bytes, i, bytes.length - i);
                }
            }
            publishProgress(100);

            outputStream.close();
            outputStream.flush();

            InputStream inputStream = connection.getInputStream();
            // read the response
            inputStream.close();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        dialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        try {
            dialog.dismiss();
        } catch(Exception e) {
        }

    }

}

2
这不是很高效,因为它在顺利进行到100之后就卡在了100%,此后对话框会在文件实际传输完毕时才消失。那么上面的代码有什么缺失吗? - Hunt
11
当你刷新outputStream时,实际上传将开始。因此,进度条是虚假的进度。 - Basbous
1
使用HttpURLConnection.setFixedLengthStreamingMode()方法上传内容时,无需缓冲(请参见@Songlin的答案)。 - German Latorre

4

我认为HttpURLConnection并不能简单地完成任务,正如@Basbous指出的那样,实际数据是在调用outputStream.flush()之前被缓冲的。根据安卓问题3164,现在已经在froyo版本(安卓2.2,sdk版本8)之后得到修复,您需要使用java.net.HttpURLConnection.setFixedLengthStreamingMode以解决缓冲行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接