Accurately display upload progress in Silverilght upload

Posted by Matt on Stack Overflow See other posts from Stack Overflow or by Matt
Published on 2010-04-21T04:18:04Z Indexed on 2010/04/21 4:23 UTC
Read the original article Hit count: 488

Filed under:
|

I'm trying to debug a file upload / download issue I'm having. I've got a Silverlight file uploader, and to transmit the files I make use of the HttpWebRequest class.

So I create a connection to my file upload handler on the server and begin transmitting. While a file uploads I keep track of total bytes written to the RequestStream so I can figure out a percentage. Now working at home I've got a rather slow connection, and I think Silverlight, or the browser, is lying to me.

It seems that my upload progress logic is inaccurate. When I do multiple file uploads (24 images of 3-6mb big in my testing), the logic reports the files finish uploading but I believe that it only reflects the progress of written bytes to the RequestStream, not the actual amount of bytes uploaded.

What is the most accurate way to measure upload progress. Here's the logic I'm using.

public void Upload()
    {
        if( _TargetFile != null )
        {
            Status = FileUploadStatus.Uploading;
            Abort = false;

            long diff = _TargetFile.Length - BytesUploaded;

            UriBuilder ub = new UriBuilder( App.siteUrl + "upload.ashx" );
            bool complete = diff <= ChunkSize;

            ub.Query = string.Format( "{3}name={0}&StartByte={1}&Complete={2}",
                                      fileName,
                                      BytesUploaded,
                                      complete,
                                      string.IsNullOrEmpty( ub.Query ) ? "" : ub.Query.Remove( 0, 1 ) + "&" );

            HttpWebRequest webrequest = ( HttpWebRequest ) WebRequest.Create( ub.Uri );
            webrequest.Method = "POST";

            webrequest.BeginGetRequestStream( WriteCallback, webrequest );
        }
    }

    private void WriteCallback( IAsyncResult asynchronousResult )
    {
        HttpWebRequest webrequest = ( HttpWebRequest ) asynchronousResult.AsyncState;
        // End the operation.
        Stream requestStream = webrequest.EndGetRequestStream( asynchronousResult );

        byte[] buffer = new Byte[ 4096 ];
        int bytesRead = 0;
        int tempTotal = 0;

        Stream fileStream = _TargetFile.OpenRead();
        fileStream.Position = BytesUploaded;
        while( ( bytesRead = fileStream.Read( buffer, 0, buffer.Length ) ) != 0 && tempTotal + bytesRead < ChunkSize && !Abort )
        {
            requestStream.Write( buffer, 0, bytesRead );
            requestStream.Flush();
            BytesUploaded += bytesRead;
            tempTotal += bytesRead;

            int percent = ( int ) ( ( BytesUploaded / ( double ) _TargetFile.Length ) * 100 );
            UploadPercent = percent;

            if( UploadProgressChanged != null )
            {
                UploadProgressChangedEventArgs args = new UploadProgressChangedEventArgs( percent, bytesRead, BytesUploaded, _TargetFile.Length, _TargetFile.Name );
                SmartDispatcher.BeginInvoke( () => UploadProgressChanged( this, args ) );
            }
        }
        //}

        // only close the stream if it came from the file, don't close resizestream so we don't have to resize it over again.
        fileStream.Close();
        requestStream.Close();
        webrequest.BeginGetResponse( ReadCallback, webrequest );

    }

© Stack Overflow or respective owner

Related posts about Silverlight

Related posts about fileupload