Search code examples
c#iosystem.net

Why the downloaded image from localhost using HttpWebRequest corrupted?


The original image(.jpg) file size is 49kb but when after I downloaded it the file size is 87kb and is corrupted. But for text files, it works. What do I need to do for downloading images using HttpWebRequest or other System.Net class? I'm using XAMPP for localhost.

//Usage: HttpDownload("http://www.localhost/files/imagine.jpg", "seo.jpg");

    static async void HttpDownload(string remoteFileOrUri, string localFileName)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(remoteFileOrUri));
        HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
        StreamReader rdr = new StreamReader(response.GetResponseStream());
        StreamWriter sw = new StreamWriter(File.OpenWrite(localFileName));

        sw.Write(rdr.ReadToEnd());
        sw.Flush();

        rdr.Close();
        sw.Close();
        Console.WriteLine("fin!");
    }

Solution

  • You shouldn't use StreamReader and StreamWriter for things that are not text. When you use them, encoding is applied. Encoding doesn't mix well with arbitrary binary data, as this blog will attest to.

    Instead you should use a simple FileStream:

    using (var output = File.OpenWrite(localFileName))
    {
        using (var responseStream = response.GetResponseStream())
        {
            await responseStream.CopyToAsync(output);
        }
    }
    

    Unfortunately, this may not be your only issue as GZip compression (if the server is using it) may also be presenting problems. You can account for this with a simple setting change:

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(remoteFileOrUri));
    
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    
    HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
    
    using (var output = File.OpenWrite(localFileName))
    {
        using (var responseStream = response.GetResponseStream())
        {
            await responseStream.CopyToAsync(output);
        }
    }