Federica Marini
Federica Marini

Reputation: 1

Upload Progress per seconds - Android

I am trying to upload a file on a server and display how many bytes are uploaded per second by this way:

public void RunUploadTest () {
    try {
        URL url = new URL(serverLink);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("content-type", "video/mp4");

        for(int i =0; i<10; i++) {
            FileInputStream fis = new FileInputStream(myFileVideo);
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            int bytesWrite = 0;
            byte[] buffer = new byte[512];
            Stopwatch timer = new Stopwatch();
            int read;
            while ((read = fis.read(buffer)) != -1&& timer.elapsedTime()<1000) {
                dos.write(buffer, 0, read);
                dos.flush();
                bytesWrite++;
            }
            Log.d("Upload", "Bytes written: " + bytesWrite*512);
        }
        fis.close();

    } catch (IOException e){
        e.printStackTrace();
    }
}

The problem is that is not calculating how many bytes are uploaded as I expect. Do you have any idea why is not working?

Upvotes: 0

Views: 155

Answers (2)

Yoni Gross
Yoni Gross

Reputation: 816

There are few problems with your code:

1. You are not counting right

This is a relatively minor issue, but the last buffer you read/write will probably not going to be 512 bytes long, so your calculation will not be precise.

you should change

    bytesWrite++;
}
Log.d("Upload", "Bytes written: " + bytesWrite*512);

to

    bytesWrite += read;
}
Log.d("Upload", "Bytes written: " + bytesWrite);

2. You are stopping the upload after 1 second anyway

The following condition:

while ((read = fis.read(buffer)) != -1&& timer.elapsedTime()<1000)

Will stop either when the file has finished reading, or 1 second elapsed. Unless a very small file, most likely file upload will stop after 1 second.

I'm not completely sure if you want an update every second, or just the average.

In case of average you should just change the while condition to:

while (read = fis.read(buffer))

And change log to:

float uploadRate = (float)(bytesWrite / timer.elapsedTime()) / 1000.0f;
String logString = String.format("Upload rate: %.2f bytes per second", uploadRate)
Log.d("Upload", logString);

In case you do want to print progress every second, you'll need to do something more fancy and expensive, like:

while (read = fis.read(buffer)) {
    dos.write(buffer, 0, read);
    dos.flush();
    bytesWrite += read;
    if (timer.shouldPrintSecondsProgress(){
        Log.d("Upload", "Bytes written: " + bytesWrite);
    }
}

StopWatch.shouldPrintSecondsProgress should be something like:

public boolean shouldPrintSecondsProgress(){
    int currentSecond = elapsedTime() / 1000;
    if (currentSecond == nextUpdate){ //I've ignored the > case, which is probably an error in our case
        nextUpdate++; //this is an int field, marking the next second cause update
        return true;
    }
    return false;
}

3. It's possible you measure only 'send' and not 'upload'

While you are sending all your data and flushing the request stream, some layer of the networking stack might have buffer/async behavior. Actually the roundtrip alone might effect calculation correctness.

It best if you close the output stream prior to measure time elapsed, and/or read the response from server (which will ensure upload is finished).

Upvotes: 0

ths
ths

Reputation: 11

If you have 10 times the same bytes written, there are 2 options:

  1. your file is written in less than 1 second;
  2. your elapsedTime method, returns in seconds(for example) and not in milliseconds

You probably don't need that for loop too, it makes you read the file 10 times.

I would rewrite your code like this:

public void RunUploadTest () {
    try {
        URL url = new URL(serverLink);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("content-type", "video/mp4");

        FileInputStream fis = new FileInputStream(myFileVideo);
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
        int bytesWrite = 0;
        byte[] buffer = new byte[512];
        int read;
        while((read = fis.read(buffer))) {
            Stopwatch timer = new Stopwatch();
            while (timer.elapsedTime()<1) { //my guess here is that this method returns in seconds
                dos.write(buffer, 0, read);
                dos.flush();
                bytesWrite += read; //taken from Yoni Gross answer
            }
            Log.d("Upload", "Bytes written: " + bytesWrite);
        }
        fis.close();

    } catch (IOException e){
        e.printStackTrace();
    }
}

Upvotes: 1

Related Questions