171

Here is my code:

protected void SaveMyImage_Click(object sender, EventArgs e)
        {
            string imageUrl = Hidden1.Value;
            string saveLocation = Server.MapPath("~/PictureUploads/whatever2.png") ; 


            HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
            WebResponse imageResponse = imageRequest.GetResponse();

            Stream responseStream = imageResponse.GetResponseStream();

            using (BinaryReader br = new BinaryReader(responseStream))
            {
                imageBytes = br.ReadBytes(500000);
                br.Close();
            }
            responseStream.Close();
            imageResponse.Close();

            FileStream fs = new FileStream(saveLocation, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fs);
            try
            {
                bw.Write(imageBytes);
            }
            finally
            {
                fs.Close();
                bw.Close();
            }
        }
}

The top imageUrl declartion is taking in a Base64 image string, and I want to convert it into an image. I think my set of code only works for images like "www.mysite.com/test.jpg" not for a Base64 string. Anybody have some suggestions? Thanks!

CRice
  • 12,279
  • 7
  • 57
  • 84
anthonypliu
  • 12,179
  • 28
  • 92
  • 154

11 Answers11

278

Here is an example, you can modify the method to accept a string parameter. Then just save the image object with image.Save(...).

public Image LoadImage()
{
    //data:image/gif;base64,
    //this image is a single pixel (black)
    byte[] bytes = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==");

    Image image;
    using (MemoryStream ms = new MemoryStream(bytes))
    {
        image = Image.FromStream(ms);
    }

    return image;
}

It is possible to get an exception A generic error occurred in GDI+. when the bytes represent a bitmap. If this is happening save the image before disposing the memory stream (while still inside the using statement).

CRice
  • 12,279
  • 7
  • 57
  • 84
119

You can save Base64 directly into file:

string filePath = "MyImage.jpg";
File.WriteAllBytes(filePath, Convert.FromBase64String(base64imageString));
INT_24h
  • 1,491
  • 1
  • 10
  • 6
  • 1
    This is an excellent solution in my case where I was using mono on Linux and experienced some odd behavior with gdi+ in Image.Save. This solution completely bypasses Image / Gdi+ (See http://stackoverflow.com/questions/35783690/mono-on-centos-6-7-gdi-exception-saving-img) – Jeff Albrecht Mar 04 '16 at 04:18
  • 2
    I tried both this and @CRice's solution (using `Image.Save()`). Both work, but for some reason this version makes my file size 30% smaller with no discernible change in image quality – Brad Mathews Jan 05 '18 at 23:28
36

Here is what I ended up going with.

    private void SaveByteArrayAsImage(string fullOutputPath, string base64String)
    {
        byte[] bytes = Convert.FromBase64String(base64String);

        Image image;
        using (MemoryStream ms = new MemoryStream(bytes))
        {
            image = Image.FromStream(ms);
        }

        image.Save(fullOutputPath, System.Drawing.Imaging.ImageFormat.Png);
    }
Austin
  • 369
  • 3
  • 3
  • 11
    This gave me an error `A generic error occurred in GDI+` described [here](http://stackoverflow.com/q/336387/345659). Moving the `image.Save` inside the using block fixed it for me. – JumpingJezza Apr 06 '16 at 13:16
  • @JumpingJezza - Of course it did... The memory stream was already disposed of... – Adrian Hum Jun 30 '22 at 09:00
14

I would suggest via Bitmap:

public void SaveImage(string base64)
{
    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
    {
        using (Bitmap bm2 = new Bitmap(ms))
        {
            bm2.Save("SavingPath" + "ImageName.jpg");
        }
    }
}
Nishant Kumar
  • 5,995
  • 19
  • 69
  • 95
9

In my case it works only with two line of code. Test the below C# code:

String dirPath = "C:\myfolder\";
String imgName = "my_mage_name.bmp";

byte[] imgByteArray = Convert.FromBase64String("your_base64_string");
File.WriteAllBytes(dirPath + imgName, imgByteArray);

That's it. Kindly up vote if you really find this solution works for you. Thanks in advance.

Milan Sheth
  • 884
  • 12
  • 11
  • 3
    It's copy of my answer (see below https://stackoverflow.com/a/35160048/4190593) :) – INT_24h Jun 06 '17 at 11:36
  • 1
    -1 because `dirPath` has to have an `@` sign before the string i..e. `@"C:\myfolder\"` or you have to escape the backslashes in the string i.e. `"C:\\myfolder\\"` – Marcus Parsons Dec 26 '18 at 16:42
  • 1
    you should provide reference to that other answer instead of taking whole credit.... – Arshi Oct 25 '19 at 13:53
9

Here is working code for converting an image from a base64 string to an Image object and storing it in a folder with unique file name:

public void SaveImage()
{
    string strm = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; 

    //this is a simple white background image
    var myfilename= string.Format(@"{0}", Guid.NewGuid());

    //Generate unique filename
    string filepath= "~/UserImages/" + myfilename+ ".jpeg";
    var bytess = Convert.FromBase64String(strm);
    using (var imageFile = new FileStream(filepath, FileMode.Create))
    {
        imageFile.Write(bytess, 0, bytess.Length);
        imageFile.Flush();
    }
}
Michael
  • 8,362
  • 6
  • 61
  • 88
7

In a similar scenario what worked for me was the following:

byte[] bytes = Convert.FromBase64String(Base64String);    
ImageTagId.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(bytes);

ImageTagId is the ID of the ASP image tag.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
abhishek
  • 79
  • 1
  • 1
6

If you have a string of binary data which is Base64 encoded, you should be able to do the following:

byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);

You should be able to write the resulting array to a file.

Lütfullah Kus
  • 302
  • 1
  • 12
afranz409
  • 772
  • 6
  • 11
  • 1
    This doesn't work. It just converts the base64 string to its binary equivalent. Writing that to a file with an image extension doesn't make it an image. – elliotwesoff Aug 28 '19 at 23:18
  • 2
    **No?** I'm sorry, this is _incorrect_. Converting a Base64 string to its _binary equivalent_ does not make it an image. (Thanks @elliotwesoff for pointing that out!) And, _why_ are you mentioning _binary data_? This question in no way mentions _binary_, or even how to convert it. – Momoro May 18 '20 at 21:02
2
public bool SaveBase64(string Dir, string FileName, string FileType, string Base64ImageString)
{
    try
    {
        string folder = System.Web.HttpContext.Current.Server.MapPath("~/") + Dir;
        if (!Directory.Exists(folder))
        {
            Directory.CreateDirectory(folder);
        }

        string filePath = folder + "/" + FileName + "." + FileType;
        File.WriteAllBytes(filePath, Convert.FromBase64String(Base64ImageString));
        return true;
    }
    catch
    {
        return false;
    }

}
KHALID
  • 21
  • 5
  • 3
    While this code may resolve the OP's issue, it is best to include an explanation as to how your code addresses the OP's issue. In this way, future visitors can learn from your post, and apply it to their own code. SO is not a coding service, but a resource for knowledge. Also, high quality, complete answers are more likely to be upvoted. These features, along with the requirement that all posts are self-contained, are some of the strengths of SO as a platform, that differentiates it from forums. You can edit to add additional info &/or to supplement your explanations with source documentation. – ysf Jun 27 '20 at 23:04
1

Using MemoryStream is not a good idea and violates a specification in MSDN for Image.FromStream(), where it says

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

A better solution is using ImageConverter, e.g:

public Image ConvertBase64ToImage(string base64)
    => (Bitmap)new ImageConverter().ConvertFrom(Convert.FromBase64String(base64));

Mehdi Dehghani
  • 10,970
  • 6
  • 59
  • 64
  • That's correct. good solution exactly when you want to use image without saving in local storage – GeeSuth Aug 14 '21 at 11:24
0

In NetCore 6.0, you can use HttpClient and the async methods in the new File class.

The implementation is very simple:

static async Task DownloadFile(string imageUrl, string pathToSave)
{
    var content = await GetUrlContent(url);
    if (content != null)
    {       
        await File.WriteAllBytesAsync(pathToSave, content);
    }
}

static async Task<byte[]?> GetUrlContent(string url)
{
    using (var client = new HttpClient())
    using (var result = await client.GetAsync(url))
        return result.IsSuccessStatusCode ? await result.Content.ReadAsByteArrayAsync():null;
}

Usage:

await DownloadFile("https://example.com/image.jpg", @"c:\temp\image.jpg");
Ester Kaufman
  • 708
  • 10
  • 20