What is the proper way to track an upload progress using RequestBuilder?

Viewed 47

I am trying to track an upload progress. I can do this when downloading by simply adding a ProgressListener to the NetworkManager

But when uploading and doing the same, I only get 1 call back with the final upload size

I see in the code that there are some private methods that deal with the Network event type

ConnectionRequest seems to have a public method that sets the request type setWriteRequest

I am using the terse RequestBuilder which by default sets the value of setWriteRequest to true as long as there is a body (which there is)

So I really don't know why only 1 callback is being returned with the upload size. Am I missing something?

My final code looks something like this

ActionListener<NetworkEvent> progressListener = new ActionListener<NetworkEvent>(){
    @Override
    public void actionPerformed(NetworkEvent evt) {
        int getSentReceived = evt.getSentReceived();//this only gets total size, no partial upload progress received
    }
};
NetworkManager.getInstance().addProgressListener(progressListener);
RequestBuilder req = Rest.post(url).body(body).header("Content-Type", "application/json").fetchAsJsonMap(resp -> {
    NetworkManager.getInstance().removeProgressListener(progressListener);
});

Edit: I have double checked this behavior on Simulator, Android and iOS

2 Answers

This hasn't worked properly for a long time: https://github.com/codenameone/CodenameOne/issues/3043

There's also this: https://github.com/codenameone/CodenameOne/issues/2087

The crux of the issue is that upload doesn't work like download. When downloading we make a request to a file and get it back. Upload writes a stream into the body of the request and then submits that request. So writing the stream to the body is fast (and shows the progress) but then the submission for us is atomic so we have no way of monitoring that.

The only real workaround is to avoid multipart upload or split your upload to smaller standalone pieces. You can use websockets which provide lower level trackable APIs.

Related