c# - 将 PNG 图像保存到内存流会导致错误

标签 c# wpf iis asp.net-web-api windows-server-2012-r2

我有一个 WebAPI 端点(托管在 IIS 中),它从数据库(字节数组)读取图像并以 PNG 格式返回它们。这段代码很简单:

  Image img = ImageHelper.ReadFromDatabase(…);
  using (MemoryStream ms = new MemoryStream())
  {
      img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
      HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
      response.Content = new ByteArrayContent(ms.ToArray());
      response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
      response.ConfigureResponseCachability(parseConceptVersion, TimeSpan.FromHours(1));
      return response;
  }

我有三个 Web 服务器,其中一个上面的代码导致了这个错误:A generic error occurred in GDI+. at at System.Drawing.Image.Save().

关于服务器的更多细节

服务器运行不同的操作系统版本:

  • 服务器 1,工作正常:Windows Server 2012 Standard
  • 服务器 2,工作正常:Windows Server 2008 R2 Standard
  • 服务器 3,不工作:Windows Server 2012 R2 Datacenter(核心)

JPEG 是一种解决方法

我更改了上面的代码以返回 JPEG 而不是 PNG,这解决了问题。

  img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

我必须发送 PNG 图片,所以我需要找到根本原因。

使用 WPF 类而不是 Windows 窗体类

我将代码转换为使用 WPF 类 (System.Windows.Media) 而不是 Windows 窗体类。结果很有趣:我在创建 PNG 时也遇到了错误。这次的错误是组件注册无效。 (HRESULT 异常:0x88982F8A)System.Windows.Media.Imaging.BitmapEncoder.SaveFrame()

服务器上是否缺少某些内容?

会不会是我的服务器缺少保存 PNG 所需的低级组件?

谢谢


@Chris Pratt 要求查看从字节数组创建图像的代码。 WebAPI 代码和 SqlDataReader 调用之间有多个层,但这里是转换从数据库读取的字节数组的代码。

/// <summary>
/// Creates a bitmap from a byte array
/// </summary>
public static Bitmap CreateBitmapFromBytes(byte[] bytes, int width, int height)
{
    // Make sure bytes were specified.
    if (bytes == null ||
        bytes.Length == 0)
    {
        return null;
    }

    using (MemoryStream imageStream = new MemoryStream(bytes))
    {
        Bitmap bitmap;

        try
        {
            bitmap = (Bitmap)Bitmap.FromStream(imageStream);
        }
        catch(ArgumentException)
        {
            return GetEmptyBitmap(width, height);
        }

        using (bitmap)
        {
            return new Bitmap(bitmap, width, height);
        }
    }
}

最佳答案

System.Drawing 命名空间在处理图像方面有很多已知的缺点。请引用this article并提供详尽的解释。

在处理这个命名空间时,您必须非常小心地放置内存流、位图等。您的问题听起来与这些一次性对象有关。

也就是说,一个好的替代方法是使用 ImageSharp library ,除其他外,它可以很好地处理从字节数组读取图像并将其保存为 png。

您可以使用 Image.Load method :

    var img = Image.Load(ImageHelper.ReadFromDatabaseAsByteArray());

save it as png到 MemoryStream 以供进一步使用:

using (var memStream = new MemoryStream())
{
   image.SaveAsPng(memStream);
   // Do something with the memStream, for example prepare http response
}

关于c# - 将 PNG 图像保存到内存流会导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35852416/

相关文章:

c# - 为什么 "new int[n] is object[]"是假的?为什么 "int[] is object[] arr"是模式错误?

c# - 无法在 Visual Studio 2012 Ultimate SP1 x64 中创建或打开网站

c# - WPF 应用程序的单元测试失败,出现 NotSupportedException "The Uri prefix is not recognized"

wpf - 覆盖自定义样式的属性

c# - 带有自定义轴标签的 xaml c# 图表

c# - 远程服务器返回错误 : (405) Method Allowed

c# - StructureMap: 'AddAllTypesOf' 没有将程序集添加到 ObjectFactory?

asp.net - 发布 asp.net MVC 后出现 403 禁止

php - 在 PHP 文件中提供 CSS(使用 IIS)

c# - 随机不是那么随机,在 Windows Phone 7 上有随机类