15

I am posting a Base64 string via Ajax to my Web Api controller. Code below

Code for converting string to Image

public static Image Base64ToImage(string base64String)
{
    // Convert base 64 string to byte[]
    byte[] imageBytes = Convert.FromBase64String(base64String);
    // Convert byte[] to Image
    using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
    {
        Image image = Image.FromStream(ms, true);
        return image;
    }
}

Controller Code

public bool SaveImage(string ImgStr, string ImgName)
{
    Image image = SAWHelpers.Base64ToImage(ImgStr);
    String path = HttpContext.Current.Server.MapPath("~/ImageStorage"); //Path

    //Check if directory exist
    if (!System.IO.Directory.Exists(path))
    {
        System.IO.Directory.CreateDirectory(path); //Create directory if it doesn't exist
    }

    string imageName = ImgName + ".jpg";

    //set the image path
    string imgPath = Path.Combine(path, imageName);

    image.Save(imgPath, System.Drawing.Imaging.ImageFormat.Jpeg);

    return true;
}

This is always failing with a generic GDI+ error. What am I missing ? Is there a better way to save a specific string as an image on a folder ?

BWA
  • 5,672
  • 7
  • 34
  • 45
w2olves
  • 2,229
  • 10
  • 33
  • 60
  • Are you sure you have write permissions to that folder? Perhaps try writing a simple text file and see if that works. Generic GDI+ errors cover a multitude of issues IMO – Matt Wilko Sep 08 '16 at 14:55
  • 5
    Why don't you save the byte[] of the image ? – Pomme De Terre Sep 08 '16 at 14:55
  • 1
    Decode to bytearray and save it as file. – BWA Sep 08 '16 at 14:55
  • 1
    Why do you use `Image` at all when you *already* have the file contents ??? – Panagiotis Kanavos Sep 08 '16 at 14:58
  • @PanagiotisKanavos what should I use ? – w2olves Sep 08 '16 at 15:01
  • @w2olves - Image is useful if you want to do actual manipulation of the image itself (resize, change colors, convert, etc). If you do not care about doing that then save the bytes directly to disk as creating an instance of type Image adds nothing of use to your logic. – Igor Sep 08 '16 at 15:07

2 Answers2

46

In Base64 string You have all bytes of image. You don't need create Image object. All what you need is decode from Base64 and save this bytes as file.

Example

public bool SaveImage(string ImgStr, string ImgName)
{       
    String path = HttpContext.Current.Server.MapPath("~/ImageStorage"); //Path

    //Check if directory exist
    if (!System.IO.Directory.Exists(path))
    {
        System.IO.Directory.CreateDirectory(path); //Create directory if it doesn't exist
    }

    string imageName = ImgName + ".jpg";

    //set the image path
    string imgPath = Path.Combine(path, imageName);

    byte[] imageBytes = Convert.FromBase64String(ImgStr);

    File.WriteAllBytes(imgPath, imageBytes);

    return true;
}
BWA
  • 5,672
  • 7
  • 34
  • 45
  • 3
    You should explain what is different from the original code and why this fixes the problem. Specifically, that `File.WriteAllBytes(imgPath, imageBytes);` is all that's needed to save the image – Panagiotis Kanavos Sep 08 '16 at 15:00
  • Thanks, answers my question and gives an education as well. This should be helpful to others in my shoes as well. – w2olves Sep 08 '16 at 15:10
  • 1
    @BWA minor typo. where is `base64String` coming from. I'd assume it's `ImgStr` – Nkosi Sep 08 '16 at 15:19
  • @Nkosi You are righ, improved. Thx – BWA Sep 08 '16 at 16:13
3

In asp net core you can get the path from IHostingEnvironment

public YourController(IHostingEnvironment env)
{
   _env = env;
}

And the method,

public void SaveImage(string base64img, string outputImgFilename = "image.jpg")
{
   var folderPath = System.IO.Path.Combine(_env.ContentRootPath, "imgs");
   if (!System.IO.Directory.Exists(folderPath))
   {
      System.IO.Directory.CreateDirectory(folderPath);
   }
   System.IO.File.WriteAllBytes(Path.Combine(folderPath, outputImgFilename), Convert.FromBase64String(base64img));
}
Gabriel P.
  • 3,400
  • 2
  • 32
  • 23