Search code examples
c#.netdotnet-httpclienthttpwebresponse

Stream.Read return System.IO.IOException


I'm trying to download a large zip (560MB) with the following code:

DateTime startTime = DateTime.UtcNow;
WebRequest request = WebRequest.Create("https://report-demo.eyeq.tech/download/Downloads.zip");
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
    using (Stream fileStream = new FileStream("Downloads.zip", FileMode.Open, FileAccess.ReadWrite))
    {
        byte[] buffer = new byte[4096];
        int bytesRead = responseStream.Read(buffer, 0, 4096);
        while (bytesRead > 0)
        {
            fileStream.Write(buffer, 0, bytesRead);
            DateTime nowTime = DateTime.UtcNow;
            if ((nowTime - startTime).TotalMinutes > 5)
            {
                throw new ApplicationException("Download timed out");
            }
            bytesRead = responseStream.Read(buffer, 0, 4096);
        }
    }
}

But after a few second of downloading, the program returned System.IO.IOException: 'The decryption operation failed, see inner exception.' And the inner Exception is: Win32Exception: The specified data could not be decrypted
EDIT: The full exception is:

Exception thrown: 'System.IO.IOException' in System.dll
System.IO.IOException: The decryption operation failed, see inner exception. ---> System.ComponentModel.Win32Exception: The specified data could not be decrypted
   --- End of inner exception stack trace ---
   at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at WpfApp1.MainWindow.<Download>d__1.MoveNext() in D:\vinh.ngo\Project\WpfApp1\MainWindow.xaml.cs:line 53

Solution

  • I can't reproduce the problem with this

    var client=new System.Net.Http.HttpClient();
    var url="https://report-demo.eyeq.tech/download/Downloads.zip";
    using var stream=await client.GetStreamAsync(url);
    using var fi=File.Create(@"c:\somepath.zip");
    //Set up a 10" timeout
    var cts=new CancellationTokenSource(TimeSpan.FromSeconds(10));
    //Copy the data directly
    await stream.CopyToAsync(fi,cts.Token);
    

    or this

    var req=System.Net.WebRequest.Create(url);
    using var response = req.GetResponse();
    using var stream = response.GetResponseStream();
    using var fi=File.Create(@"c:\somepath.zip");
    //Set up the timeout
    var cts=new CancellationTokenSource(TimeSpan.FromSeconds(10));
    //Store the data
    await stream.CopyToAsync(fi,cts.Token);
    Console.WriteLine("Finished");
    

    In .NET Core 3.1 WebRequest uses HttpClient so there's not a huge difference between those snippets.

    The only thing that encrypts/decrypts data in this code is the SSL connection. To get a decryption error means the connection was somehow affected. Perhaps the server dropped the connection resulting in incomplete packages that failed decryption? Or the connection was interrupted and some data was lost? Is Fiddler or some other debugging proxy used perhaps?

    Update

    I changed to LAN and it worked all Wi-Fi connections fail one way or another. Perhaps the signal is weak, or noisy neighbors emit on the same channel, or the telco's cheap router decided to drop some packages out of spite. An overworked router in a cafe may not have the CPU power to handle all connections so it will start dropping low priority packages after a while