How to download image from URL

C#UrlDownload

C# Problem Overview


Is there a way to download an image directly from a url in c# if the url does not have an image format at the end of the link? Example of URL:

https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-xpf1/v/t34.0-12/10555140_10201501435212873_1318258071_n.jpg?oh=97ebc03895b7acee9aebbde7d6b002bf&oe=53C9ABB0&__gda__=1405685729_110e04e71d969d392b63b27ec4f4b24a

I know how to download the image when the url ends with an image format. Eg:

http://img1.wikia.nocookie.net/__cb20101219155130/uncyclopedia/images/7/70/Facebooklogin.png

C# Solutions


Solution 1 - C#

Simply You can use following methods.

using (WebClient client = new WebClient()) 
{
	client.DownloadFile(new Uri(url), @"c:\temp\image35.png");
	// OR 
	client.DownloadFileAsync(new Uri(url), @"c:\temp\image35.png");
}

These methods are almost same as DownloadString(..) and DownloadStringAsync(...). They store the file in Directory rather than in C# string and no need of Format extension in URi

If You don't know the Format(.png, .jpeg etc) of Image

public void SaveImage(string imageUrl, string filename, ImageFormat format)
{    
	WebClient client = new WebClient();
	Stream stream = client.OpenRead(imageUrl);
	Bitmap bitmap;  bitmap = new Bitmap(stream);

	if (bitmap != null)
	{
		bitmap.Save(filename, format);
	}
        
	stream.Flush();
	stream.Close();
	client.Dispose();
}

Using it

try
{
	SaveImage("--- Any Image URL---", "--- Any Image Path ---", ImageFormat.Png)
}
catch(ExternalException)
{
	// Something is wrong with Format -- Maybe required Format is not 
	// applicable here
}
catch(ArgumentNullException)
{ 	
	// Something wrong with Stream
}

Solution 2 - C#

Depending whether or not you know the image format, here are ways you can do it :

Download Image to a file, knowing the image format

using (WebClient webClient = new WebClient()) 
{
   webClient.DownloadFile("http://yoururl.com/image.png", "image.png") ; 
}

Download Image to a file without knowing the image format

You can use Image.FromStream to load any kind of usual bitmaps (jpg, png, bmp, gif, ... ), it will detect automaticaly the file type and you don't even need to check the url extension (which is not a very good practice). E.g:

using (WebClient webClient = new WebClient()) 
{
    byte [] data = webClient.DownloadData("https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-xpf1/v/t34.0-12/10555140_10201501435212873_1318258071_n.jpg?oh=97ebc03895b7acee9aebbde7d6b002bf&oe=53C9ABB0&__gda__=1405685729_110e04e71d9");

   using (MemoryStream mem = new MemoryStream(data)) 
   {
       using (var yourImage = Image.FromStream(mem)) 
       { 
          // If you want it as Png
           yourImage.Save("path_to_your_file.png", ImageFormat.Png) ; 

          // If you want it as Jpeg
           yourImage.Save("path_to_your_file.jpg", ImageFormat.Jpeg) ; 
       }
   } 

}

Note : ArgumentException may be thrown by Image.FromStream if the downloaded content is not a known image type.

Check this reference on MSDN to find all format available. Here are reference to WebClient and Bitmap.

Solution 3 - C#

.NET has changed a bit over the years, making the other answers on this post pretty dated:

  • They use Image from System.Drawing (which is not available for .NET Core) to find the image format
  • They use System.Net.WebClient which is deprecated > We don't recommend that you use the WebClient class for new development. Instead, use the System.Net.Http.HttpClient class.

.NET Core asynchronous solution

Getting the file extension

The first part of getting the file extension is to remove all the unnecessary parts from the URL. We can use Uri.GetLeftPart() with UriPartial.Path to get everything from the Scheme up to the Path.
In other words, https://www.example.com/image.png?query&with.dots becomes https://www.example.com/image.png.

After that, we can use Path.GetExtension() to get only the extension (in my previous example, .png).

var uriWithoutQuery = uri.GetLeftPart(UriPartial.Path);
var fileExtension = Path.GetExtension(uriWithoutQuery);

Downloading the image

From here it should be straight forward. Download the image with HttpClient.GetByteArrayAsync, create the path, ensure the directory exists and then write the bytes to the path with File.WriteAllBytesAsync()

private async Task DownloadImageAsync(string directoryPath, string fileName, Uri uri)
{
    using var httpClient = new HttpClient();

    // Get the file extension
    var uriWithoutQuery = uri.GetLeftPart(UriPartial.Path);
    var fileExtension = Path.GetExtension(uriWithoutQuery);

    // Create file path and ensure directory exists
    var path = Path.Combine(directoryPath, $"{fileName}{fileExtension}");
    Directory.CreateDirectory(directoryPath);

    // Download the image and write to the file
    var imageBytes = await httpClient.GetByteArrayAsync(uri);
    await File.WriteAllBytesAsync(path, imageBytes);
}

Note that you need the following using directives.

using System;
using System.IO;
using System.Threading.Tasks;
using System.Net.Http;

Example usage

var folder = "images";
var fileName = "test";
var url = "https://cdn.discordapp.com/attachments/458291463663386646/592779619212460054/Screenshot_20190624-201411.jpg?query&with.dots";

await DownloadImageAsync(folder, fileName, new Uri(url));

Notes

  • It's bad practice to create a new HttpClient for every method call. It is supposed to be reused throughout the application. I wrote a short example of an ImageDownloader(50 lines) with more documentation that correctly reuses the HttpClient and properly disposes of it that you can find here.

Solution 4 - C#

For anyone who wants to download an image WITHOUT saving it to a file:

Image DownloadImage(string fromUrl)
{
	using (System.Net.WebClient webClient = new System.Net.WebClient())
	{
		using (Stream stream = webClient.OpenRead(fromUrl))
		{
			return Image.FromStream(stream);
		}
	}
}

Solution 5 - C#

.net Framework allows PictureBox Control to Load Images from url

and Save image in Laod Complete Event

protected void LoadImage() {
 pictureBox1.ImageLocation = "PROXY_URL;}

void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e) {
   pictureBox1.Image.Save(destination); }

Solution 6 - C#

Most of the posts that I found will timeout after a second iteration. Particularly if you are looping through a bunch if images as I have been. So to improve the suggestions above here is the entire method:

public System.Drawing.Image DownloadImage(string imageUrl)
    {
        System.Drawing.Image image = null;

        try
        {
            System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);
            webRequest.AllowWriteStreamBuffering = true;
            webRequest.Timeout = 30000;
            webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
            webRequest.ServicePoint.MaxIdleTime = 5000;

            using (System.Net.WebResponse webResponse = webRequest.GetResponse())
            {

                using (System.IO.Stream stream = webResponse.GetResponseStream())
                {
                    image = System.Drawing.Image.FromStream(stream);
                }
            }

            webRequest.ServicePoint.CloseConnectionGroup(webRequest.ConnectionGroupName);
            webRequest = null; 
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message, ex);

        }
       

        return image;
    }

Solution 7 - C#

This method did it for me,

I got the main code from here

then using this fix

I was able to make a method that could get around the dreaded forbidden 403 error

Here is the method

    private static void DownloadImage(string url, string saveFilename)
    {
        var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
        // we need the user agent and default credentials if not,
        //  we get a forbidden request 303 error, which pretty much means the server thinks we are a bot -- which we are.... hehehehehehe
        httpWebRequest.UserAgent = "Case Banana"; // note -- this string can be anything you like, I recommend making it atleast 10 characters
        httpWebRequest.UseDefaultCredentials = true;

        var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        if ((httpWebResponse.StatusCode != HttpStatusCode.OK &&
            httpWebResponse.StatusCode != HttpStatusCode.Moved &&
            httpWebResponse.StatusCode != HttpStatusCode.Redirect)
            || !httpWebResponse.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
        {
            return;
        }

        using (var stream = httpWebResponse.GetResponseStream())
        {
            using (var fileStream = File.OpenWrite(saveFilename))
            {
                var bytes = new byte[4096];
                var read = 0;
                do
                {
                    if (stream == null)
                    {
                        continue;
                    }
                    read = stream.Read(bytes, 0, bytes.Length);
                    fileStream.Write(bytes, 0, read);
                } while (read != 0);
            }
        }
    }

Solution 8 - C#

Everyone has given a great solution for this problem but theere is a main issue behind all solutions given by everyone and that it will not create SSL/TLS secure channel if the image is hosted on https So, what should we do then? Answer is simple just add these 2 lines before creating a WebClient request

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Solution 9 - C#

Try this it worked for me

Write this in your Controller

public class DemoController: Controller

        public async Task<FileStreamResult> GetLogoImage(string logoimage)
        {
            string str = "" ;
            var filePath = Server.MapPath("~/App_Data/" + SubfolderName);//If subfolder exist otherwise leave.
            // DirectoryInfo dir = new DirectoryInfo(filePath);
            string[] filePaths = Directory.GetFiles(@filePath, "*.*");
            foreach (var fileTemp in filePaths)
            {
                  str= fileTemp.ToString();
            }
                return File(new MemoryStream(System.IO.File.ReadAllBytes(str)), System.Web.MimeMapping.GetMimeMapping(str), Path.GetFileName(str));
        }
       
         

Here is my view

<div><a href="/DemoController/GetLogoImage?Type=Logo" target="_blank">Download Logo</a></div>
   

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIfwat IbrahimView Question on Stackoverflow
Solution 1 - C#CharlieView Answer on Stackoverflow
Solution 2 - C#Perfect28View Answer on Stackoverflow
Solution 3 - C#MarcusOtterView Answer on Stackoverflow
Solution 4 - C#Brian CryerView Answer on Stackoverflow
Solution 5 - C#Ali HumayunView Answer on Stackoverflow
Solution 6 - C#Be05x5View Answer on Stackoverflow
Solution 7 - C#JamiscoView Answer on Stackoverflow
Solution 8 - C#lets CodeView Answer on Stackoverflow
Solution 9 - C#Chandan KumarView Answer on Stackoverflow