gdi+ error saving image from webpage

2019-09-08 15:26发布

问题:

I have such method for saving image from url:

public Image DownloadImage(string _URL)
        {
            Image _tmpImage = null;

            try
            {
                // Open a connection
                System.Net.HttpWebRequest _HttpWebRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(_URL);

                _HttpWebRequest.AllowWriteStreamBuffering = true;

                // You can also specify additional header values like the user agent or the referer: (Optional)
                _HttpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0";
                _HttpWebRequest.Referer = url;

                // set timeout for 20 seconds (Optional)
                _HttpWebRequest.Timeout = timeout;

                // Request response:
                System.Net.WebResponse _WebResponse = _HttpWebRequest.GetResponse();

                // Open data stream:
                System.IO.Stream _WebStream = _WebResponse.GetResponseStream();

                // convert webstream to image
                _tmpImage = Image.FromStream(_WebStream);

                // Cleanup
                _WebResponse.Close();
            }
            catch (Exception e)
            {
                // Error
                new Log(id++, DateTime.Now, e.ToString() + e.Message);
                return null;
            }

            return _tmpImage;
        }

and call this method:

Image _Image = null;
                _Image = DownloadImage("https://***" + img_url);


System.Runtime.InteropServices.ExternalException (0x80004005): В GDI+ error occured
   in System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
   in System.Drawing.Image.Save(String filename, ImageFormat format)
   in System.Drawing.Image.Save(String filename)
   in konslat.TermSh.getAndSaveImage() в 

what i do wrong, and how to solve this?

回答1:

The exception is raised because you call _WebResponse.Close() which in turn closes the underlying Stream object, but according to MSDN documentation for Image.FromStream method

You must keep the stream open for the lifetime of the Image.

So to solve your problem you need to create a copy of your _tmpImage before closing the _WebResponse. This answer to similar question has a sample code.
Update
Here is sample code - Console application with references to System.dll, System.Core.dll and System.Drawing.dll, target framework version 4:

using System;  
using System.Drawing;  
using System.Drawing.Imaging;  
using System.IO;  
using System.Net;  
namespace SaveImage
{
class Program
{
    static void Main(string[] args)
    {
        using (Image image = DownloadImage(new Uri("http://www.hdwallpapersview.com/wp-content/uploads/2013/10/30/omg-funny-animals-dog-1.jpg")))
        {
            image.Save("temp.jpg", ImageFormat.Jpeg);
        }
    }
    public static Image DownloadImage(Uri url)
    {
        Image result = null;
        try
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.AllowWriteStreamBuffering = true;
            webRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0";
            WebResponse webResponse = webRequest.GetResponse();
            using (Stream webStream = webResponse.GetResponseStream())
            {
                using (Image tempImage = Image.FromStream(webStream))
                {
                    result = new Bitmap(tempImage);
                }
            }
            webResponse.Close();
        }
        catch (Exception e)
        {
            return null;
        }

        return result;
    }
}

}