Home » .Net FrameworkRSS

how to show upload progress in steps

Hi,

I have a desktop application which takes photos and upload to a web server. I am using HttpWebRequest and HttpWebResponse classes to make request and get response. I am showing progressbar on the UI to show upload process. Everything is working fine. But since I am getting the status, when one file gets uploaded completely, my progressbar looks frozen, till the complete file upload.

var responseFromServer = ServiceRequest.GetResponsePhoto(" AddPhotos" , " ServiceInstances" , photoToUpload, serviceInstanceID.ToString());
var response = responseFromServer.Deserialize>();
bool success = (bool )response[" success" ];



ServiceRequest class takes care of making a request and getting response from server.
HttpWebResponse.GetResponseStream method gives response for the complete upload of one file. I want to know if there is any way I could able to know intermediate upload steps which I can show on the progressbar which makes UI more interactive.

Any help or any sample will be greatly appreciated.

Veena
 

11 Answers Found

 

Answer 1

Yeah,  if you need intermediate progress  indications, you should upload  the data asynchronously.

For that, get the stream as before..

Stream requestStream = request.GetRequestStream();

Byte [] photo = readPhotograph(..); // get the photo into a byte array. Or alternately, read from a stream.

int totalSize = photo.Length;

int offset = 0;
int totalWritten = 0;
void ReadCallback(IAsyncResult ar)
{
Stream stream = ar.AsyncState as Stream;
try
{
int written = stream.EndRead(ar);
offset += written;
totalWritten += written;
// here, update dialog box.
this.updateProgress(totalWritten, totalSize);

if (totalWritten < totalSize)
{
    int chunkSize = Math.Min(1024, (totalSize-totalWritten));
   // kick off another async write
   stream.BeginWrite(photo, offset, chunkSize, new AsyncCallback(ReadCallback), stream);
}
}
}

The code snippet needs some work to separate out state variables, but you get the idea...
int chunkSize = Math.Min(totalSize, 1024) // write in 1k chunks.
requestStream.BeginWrite(photo, 0, chunkSize, new AsyncCallback(WriteCallback), requestStream);

in your callback...


 

Answer 2

You don't even NEED to do the upload  asynchronously (although that's generally a much better pattern anyways, as it allows your UI to continue to be responsive to user input during the upload).  As long as you set either HttpWebRequest.ContentLength or HttpWebRequest.SendChunked before calling GetRequestStream, the data you send will be sent to the server  with each call to Stream.[Begin]Write.  If you write the file  in small chunks as Feroze suggests, you can get an idea of how far along you.

As a slight caution on this approach, the writes complete  when the data has been sent, NOT when it has actually been received by the server.  On a high-latency connection, the last chunk of data may be sent well before the server actually receives it.  It may be worth reserving some space at the end of your progress  bar for the call to [Begin]GetResponse, after which you can actually be sure that the server has received the entire file.

As another caution, writing lots of small chunks can be less efficient than writing a few large chunks.  If raw upload speed is important to your application, it may be worth writing the file in large chunks and not being as precise with the progress bar.

-dave

 

Answer 3

That is a good point, Dave. I had'nt thought about the fact that this would only track completions on the client, not the actual reception of data on the server.

Also, you made some good points about chunk sizes.
 

Answer 4

Thanks Feroze and Dave,

I will try HttpWebRequest.ContentLength or HttpWebRequest.SendChunked.


Veena
 

Answer 5

I am sorry to get back so late.
But I can not find a way to read a requestStream (no beginRead). I wrote a code like this


 StreamReader GetUrlStream(string url, HttpWebRequest webRequest, Dictionary<string, string> postKeys)
        {
            try
            {
                if (webRequest == null)
                {
                    webRequest = (HttpWebRequest)System.Net.WebRequest.Create(url);
                }

               
                webRequest.Credentials = new NetworkCredential("VersentiaUser", "password");          

                webRequest.Method = "POST";
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.SendChunked = true;
              
                ms = AddPostKeys(postKeys);
                totalSize = (int)ms.Length;
                webRequest.ContentLength = totalSize;            

               
               
               Stream requestStream =  webRequest.GetRequestStream();
               
                chunkSize = Math.Min(2048 , totalSize);

                requestStream.BeginWrite(ms.ToArray(), 0, chunkSize, WriteCallback, requestStream);

              
                ms.Close();
                ms.Dispose();               
                startTime = DateTime.Now;             

              
                WebResponse response  = (HttpWebResponse)webRequest.GetResponse();
                endTime = DateTime.Now;

                Encoding enc = Encoding.GetEncoding(1252);

           
                var  strResponse = new StreamReader(response.GetResponseStream(), enc);

                return strResponse;
            }
            catch (WebException ex)
            {
               
                return null;
            }
           
        }


        private void WriteCallback(IAsyncResult asynchronousResult)
        {
            Stream requestStream = (Stream) asynchronousResult.AsyncState;
            requestStream.EndWrite(asynchronousResult);

            totalWritten += chunkSize;
            chunkSize = Math.Min(2048, (totalSize - totalWritten));

            if (totalWritten < totalSize)
            {
                requestStream.BeginWrite(ms.ToArray(), totalWritten, chunkSize, WriteCallback, requestStream);
               
            }
            requestStream.Close();
            requestStream.Dispose();
           
        }

But I got Exception that "Concurrent IO read write operation is not allowed".

Please help.

Veena

 

Answer 6

Sorry if I get you on another track without looking at your code first, but be sure to also check out the backgroundworker component: http://msdn.microsoft.com/en-us/library/8xs8549b.aspx
 

Answer 7

Thanks Naicul,

But I am looking for something which shows upload  file status  as file  is uploaded  to server. Actually HttpWebRequest and HttpWebresponse classes  has no arrangement to write requestStream or read  responseStream in steps, so The status comes to know when the file is uploaded completely. That's why uploadBar looks frozen  until I get the response  back.

I am uploading pictures, I want to give assurance of upload progress  to user  by showing  uploadRate and showing a continuous upload bar.

If you have any idea, please help.


Veena
 
 

Answer 9

Thanks Naicul,

But I am uploading a file  from my computer to web  server and I find no way to know how much data is uploaded  until complete  file is uploaded.

I was trying to read the requestStream in chunks , but no luck.

Veena
 

Answer 10

Hello,

As this post is for 9 month ago I want to if you find any solution? I have the same problem in uploading and I need a progress  bar for my uploads. I will appreciate it if you share your solution...

 

best wishes

 

Answer 11

Sorry, Not yet.
 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Tech Videos   |   Follow us on Twitter