0

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?

brabertaser19
  • 5,678
  • 16
  • 78
  • 184

1 Answers1

2

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;
    }
}

}

Community
  • 1
  • 1
Yurii
  • 4,811
  • 7
  • 32
  • 41
  • did you mean _tmpImage = Image.FromStream(_WebStream); _tmpImage2 = _tmpImage; and return _tmpImage2; or what, please give code here – brabertaser19 Nov 29 '13 at 18:00
  • @brabertaser1992 almost, here is what I meant `_tmpImage = Image.FromStream(_WebStream); imageToReturn = new BitMap(_tmpImage);` and `return imageToReturn;`. Your sample will simply create another reference to the same image instance. Hope this helps. – Yurii Nov 29 '13 at 18:08
  • hm( Error 1 The type or namespace name 'BitMap' could not be found (are you missing a using directive or an assembly reference?) but i added reference, using... – brabertaser19 Nov 29 '13 at 18:23
  • @brabertaser1992, sorry i mistyped the class name it should be `Bitmap` in `System.Drawing` namespace. – Yurii Nov 29 '13 at 18:29
  • Have you added reference to `System.Drawing.dll` and using directive `using System.Drawing;`? – Yurii Nov 29 '13 at 18:43
  • That's rather strange behaviour, try cleaning and rebuilding the solution, if it doesn't help then there is some issue with your environment. Also I'm not sure about this approach but you can try this line of code `imageToReturn = (Image)_tmpImage.Clone();` – Yurii Nov 29 '13 at 18:57
  • maybe i will give you my test project, and you will take a look ? last code didn't help\ – brabertaser19 Nov 29 '13 at 19:04
  • so what do you think? maybe chat? – brabertaser19 Nov 29 '13 at 19:18
  • и пропал куда-то ( бедапечаль – brabertaser19 Nov 29 '13 at 19:47