showing a progress bar during file upload

2019-02-27 04:17发布

问题:

I've got an async task that is supposed to show progress during a file upload. Everything is working except that it looks like it finishes the file upload really really fast, and then it just sits there at 100% waiting.

I traced this down to

URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();

// 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("Content-Type", "multipart/form-data;boundary=" + boundary);

outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"Filedata\";filename=\"" + pathToOurFile + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
long totalBytesWritten = 0;
while (bytesRead > 0) {
    outputStream.write(buffer, 0, bufferSize);
    outputStream.flush();
    if (mCancel) { throw new CancelException(); }

    totalBytesWritten += bufferSize;
    if (mProgressDialog != null) { 
            mProgressDialog.setProgress(Integer.valueOf((int) (totalBytesWritten / 1024L))); 
    }

    bytesAvailable = fileInputStream.available();
    bufferSize = Math.min(bytesAvailable, maxBufferSize);
    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

// Responses from the server (code and message)
int serverResponseCode = connection.getResponseCode();

What I noticed is that there's no real delay until the very last line where it's getting the response code. I think what's happening is that the data is getting buffered so it looks like it has uploaded it, but hasn't really - it has just buffered it. Then when i get to the getResponseCode() call, it has no choice but to finish the upload to get the upload status. is there any way to make it actually upload along the way so i can get a reasonable progress?

回答1:

This is how HTTP Post is designed to work so do not expect it to give you progress details.

You can use one of the several file uploader components available in the market. They internally use flash or silverlight or iframes to show the progress.

http://dhtmlx.com/docs/products/dhtmlxVault/index.shtml

http://www.element-it.com/multiple-file-upload/flash-uploader.aspx

You will find many such others if you google a bit.

They internally use raw IO instead of http post to handle multiple files and progress notification. Yahoo and Google also uses such techniques for making attachments to mail.

If you are really feeling adventurous, you can recreate the wheel - i.e. write your own component.

Edit:

Please specify if you want to do this in a windows desktop application or a web application.



回答2:

You can use Progress Dialog class as follows,

ProgressDialog progDailog = ProgressDialog.show(this,"Uploading", "Uploading File....",true,true);

new Thread ( new Runnable()
{
     public void run()
     {
      // your loading code goes here
     }
}).start();

Handler progressHandler = new Handler() 
{
     public void handleMessage(Message msg1) 
     {
         progDailog.dismiss();
     }
}


回答3:

You can try using a AsyncTask ...

create a progress dialog in onPreExecute method and dismiss the dialog in onPostExecute method..

Keep the upload method in doInBackground()

example :

public class ProgressTask extends AsyncTask<String, Void, Boolean> {

    public ProgressTask(ListActivity activity) {
        this.activity = activity;
        dialog = new ProgressDialog(context);
    }

    /** progress dialog to show user that the backup is processing. */
    private ProgressDialog dialog;

    protected void onPreExecute() {
        this.dialog.setMessage("Progress start");
        this.dialog.show();
    }

        @Override
    protected void onPostExecute(final Boolean success) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }           
    }

    protected Boolean doInBackground(final String... args) {

// your upload code

          return true;
       }
    }
}


回答4:

HttpURLConnection.setFixedLengthStreamingMode(...) did the trick!



回答5:

You can do like:

try { // open a URL connection to the Servlet
            FileInputStream fileInputStream = new FileInputStream(
                    sourceFile);
            URL url = new URL("http://10.0.2.2:9090/plugins/myplugin/upload");
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true); // Allow Inputs
            conn.setDoOutput(true); // Allow Outputs
            conn.setUseCaches(false); // Don't use a Cached Copy
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("ENCTYPE", "multipart/form-data");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data;boundary=" + boundary);
            conn.setRequestProperty("uploadedfile", filename);
            // conn.setFixedLengthStreamingMode(1024);
            // conn.setChunkedStreamingMode(1);
            dos = new DataOutputStream(conn.getOutputStream());
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
                    + filename + "\"" + lineEnd);
            dos.writeBytes(lineEnd);
            bytesAvailable = fileInputStream.available();
            bufferSize = (int) sourceFile.length()/200;//suppose you want to write file in 200 chunks
            buffer = new byte[bufferSize];
            int sentBytes=0;
            // read file and write it into form...
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            while (bytesRead > 0) {
                dos.write(buffer, 0, bufferSize);
                // Update progress dialog
                sentBytes += bufferSize;
                publishProgress((int)(sentBytes * 100 / bytesAvailable));
                bytesAvailable = fileInputStream.available();
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            }
            // send multipart form data necesssary after file data...
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
            // Responses from the server (code and message)
            serverResponseCode = conn.getResponseCode();
            String serverResponseMessage = conn.getResponseMessage();
            // close streams
            fileInputStream.close();
            dos.flush();
            dos.close();
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }