将Base64字符串转换为图像并保存

174

这是我的代码:

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

顶部的imageUrl声明接收一个Base64图像字符串,我想将其转换为图像。 我认为我的代码集仅适用于像“www.mysite.com/test.jpg”这样的图像,而不适用于Base64字符串。 有人有建议吗? 谢谢!


尝试使用以下代码:byte[] bytesContent = Convert.FromBase64String(Str64File); - گلی
11个回答

280

这里有一个示例,您可以修改方法以接受字符串参数。然后只需使用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;
}

当字节表示位图时,可能会出现异常A generic error occurred in GDI+.。 如果出现这种情况,请在内部使用语句的情况下在释放内存流之前保存图像。


1
这个方法给我返回了一个黑色的矩形,你有什么想法吗? - katmanco
73
是的,这是一个黑像素:R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw== - CRice
7
@katmanco 我认为黑色像素是作为示例提供的。请尝试用您自己的base64字符串替换示例base64字符串。 - kallotec
5
你可能需要添加对 System.Drawing DLL 的引用。 - Philip Rego
2
@Bibin 你尝试在 using 语句内保存图像了吗? - CRice
显示剩余8条评论

123

您可以直接将Base64保存到文件中:

string filePath = "MyImage.jpg";
File.WriteAllBytes(filePath, Convert.FromBase64String(base64imageString));

1
这是一个在我使用Linux上的mono时,遇到了一些图像处理奇怪行为的绝佳解决方案。该方案完全绕过了Image / Gdi+(请参见http://stackoverflow.com/questions/35783690/mono-on-centos-6-7-gdi-exception-saving-img)。 - Jeff Albrecht
2
我尝试了这个和@CRice的解决方案(使用Image.Save())。两者都可以,但由于某种原因,这个版本使我的文件大小减小了30%,而图像质量没有明显变化。 - Brad Mathews

36

这是我最终选择的方案。

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

11
这使我遇到了一个错误:“GDI+ 发生了一般性错误”,可以在这里找到描述。将 image.Save 放入 using 块中解决了我的问题。 - JumpingJezza
@JumpingJezza - 当然了...内存流已经被处理掉了... - Adrian Hum

14

我建议通过位图:

public void SaveImage(string base64)
{
    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
    {
        using (Bitmap bm2 = new Bitmap(ms))
        {
            bm2.Save("SavingPath" + "ImageName.jpg");
        }
    }
}

3
使用位图和不使用位图转换的区别是什么?谢谢。 - Amine Da.

9

以下是将base64字符串转换为Image对象并将其存储在具有唯一文件名的文件夹中的工作代码:

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

9

对我来说,只需要两行代码就可以工作。请测试以下C#代码:

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

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

这就是全部。如果你真的发现这个解决方案对你有用,请点赞。提前谢谢。

3
这是我的回答的副本(请参见下面的链接 https://dev59.com/Rm035IYBdhLWcg3weP7f#35160048) :) - INT_24h
1
返回-1,因为dirPath字符串前必须有@符号,例如@"C:\myfolder\",或者您必须在字符串中转义反斜杠,例如"C:\\myfolder\\" - Marcus Parsons
1
你应该提供对其他答案的参考,而不是完全把功劳归于自己... - Arshi

7

在类似的情况下,我所采用的方法是:

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

ImageTagId是ASP图像标签的ID。


6
如果您有一串Base64编码的二进制数据,您应该能够执行以下操作:
byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);

你应该能够将结果数组写入文件。


1
这样做不起作用。它只是将base64字符串转换为其二进制等效形式。将其写入具有图像扩展名的文件并不能使其成为图像。 - elliotwesoff
2
不好意思,这是错误的。将Base64字符串转换为其二进制等效物并不能使它成为图像。(感谢@elliotwesoff指出!)而且,你为什么要提到二进制数据?这个问题根本没有提到二进制,甚至没有提到如何进行转换。 - Momoro

2

使用 MemoryStream 不是一个好主意,并且违反了 MSDN 对于 Image.FromStream() 的规范,其中它说

你必须在 Image 的生命周期内保持流处于打开状态。

更好的解决方案是使用 ImageConverter,例如:

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


没错。当你想使用图像而不保存在本地存储时,这是一个很好的解决方案。 - GeeSuth

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

}

3
虽然这段代码可能解决了提问者的问题,但最好还是解释一下你的代码如何解决了提问者的问题。这样,未来的访问者就可以从你的帖子中学习,并将其应用到自己的代码中。SO不是一个编码服务,而是一个知识资源。高质量、完整的答案更有可能被点赞。这些特点以及所有帖子都必须独立自包含的要求是SO作为一个平台的优势之一,这也使它与论坛有所区别。你可以编辑帖子添加其他信息和/或使用源文件文档来补充解释。 - ysf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接