views:

97

answers:

3

Using the following code (from a Silverlight 4 OOB app) I'm getting a result stream with a size of zero even though it takes the time to download the whole file (900+MB) and no error is reported. Fiddler also says the whole file was downloaded.

The handler on progress changed (although not shown below) is hit and reports an increase in download percentage.

This works with smaller files (10MB).

var wc = new WebClient();
wc.OpenReadCompleted += DownloadWholeFileOpenReadCompleted;
wc.DownloadProgressChanged += DownloadWholeFileDownloadProgressChanged;

wc.OpenReadAsync(new Uri(movie.DownloadUrl, UriKind.Absolute));


private static void DownloadWholeFileOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        return; // this is not hit
    }

    if (e.Error != null)
    { 
        return; // this is not hit
    }

    using (var fs = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
    {
        var buffer = new byte[4096];
        int bytesRead;

        // <snip />

        // e.Result.Length this equals 0

        while ((bytesRead = e.Result.Read(buffer, 0, buffer.Length)) != 0)
        {
            fs.Write(buffer, 0, bytesRead);
        }

        fs.Close();
    }

    // <snip />
}

Any ideas?

+1  A: 

My guess is because the underlying stream is a chunked response and no Content Length header was given in the HTTP response. So Length returns 0. There's nothing about using the Length in the class spec. According to the spec:

You should check the Error and Cancelled properties before using the data that is returned by this property. If the Error property's value is an Exception object or the Cancelled property's value is true, the asynchronous operation did not complete correctly and the Result property's value will not be valid.

So I would ignore Length, check those fields, and then read to your heart's content.

SB
As in the code sample I am checking cancelled and error but they indicate no problem.
Matt Lacey
So then you should be fine reading from the stream. The point is you can't rely on length unfortunately. HTTP responses are not required to put that in the headers, and I imagine that you'll find anytime you have a valid Length field (like with the 10MB files) that a Content-Length header was present.
SB
A: 

There is a default 4Mb limit for data downloads. Have you increased it?

Try this link: http://forums.silverlight.net/forums/p/21513/75649.aspx

<system.web>
    ... 
   <httpRuntime maxRequestLength="xxx" /> // Size in Kb
</system.web>
Enough already
I'm not uploading, I'm downloading and it copes with 10MB fine so that's defineitely not it.
Matt Lacey
@Matt Lacey: I meant download *fixed now* :) At what size *does* it fail? That in itself may give you a clue.
Enough already
A: 

Apparently, there is a "known issue" with using WebClient and very large files. In some cases this may be linked to issues with the Content-Length not being set by the server.

Based on the data captured via Fiddler2, the header is being set correctly.
I am therefore assuming that this is not the cause of my specific issue.

Apparently, this issue does not exist with HttpWebRequest, so I'll look at changing to use that instead.

Matt Lacey
Where's the issue described?
SB
@SB at the moment only in an email from someone at Microsoft. I've asked where/if this is documented but have yet to receive a response.
Matt Lacey