在IIS7中将png保存到MemoryStream时,GDI +中发生了一般错误

时间:2012-10-23 13:49:46

标签: .net iis-7 bitmap png memorystream

当我尝试将png保存到内存流时出错。在我的ASP.NET开发服务器上,一切正常,但是当我在IIS7下运行网站时 - 会产生错误。当我尝试保存jpg格式时 - 一切都正确。在IIS中,我将.NET可信级别设置为完全。但它仍然不起作用。我需要你的帮助。

private static Stream DrawBarChart(IEnumerable<Tuple<string, ulong, double>> data){
using (MemoryStream stream = new MemoryStream())
{
    var canvasWidth = PageSize.A4.Width;
    var canvasHeight = PageSize.A4.Height;

    using (
        System.Drawing.Image bitmap = new Bitmap((int) canvasWidth,
                                                 (int) canvasHeight))
    {
        using (var graphics = Graphics.FromImage(bitmap))
        {
            var penBlack1 = new Pen(Brushes.Black, 1);

            graphics.DrawLine(penBlack1, 0, 0, canvasWidth, 0);
            graphics.DrawLine(penBlack1, 0, 0, 0, canvasHeight);

            graphics.Save();
        }
        bitmap.Save(stream, ImageFormat.Png);

    stream.Flush();
    stream.Position = 0;

    return stream;
    }
}

}

1 个答案:

答案 0 :(得分:3)

代码中至少有2个完全独立的问题导致其出现故障。

问题#1:GDI +错误

这是一个反复出现的问题,不断涌现在生态系统的各个角落。 我有它,我设法解决它,现在我不记得到底是怎么回事。 我试图复制你的问题而我没有收到失败。

我建议您查看此主题:http://forums.asp.net/t/624305.aspx/1 在这里,有些人乐意通过以下方式克服这个问题:

  • 确保在继续使用其他图纸之前处置了所有的Bitmap实例
  • 有趣的一个):执行 GC.Collect()(可能在每个位图渲染后)

这不是我想尝试帮助您解答的主要原因。 看起来你已经做了(你说你做了)我通常做的所有事情,以确保我不会在这种情况下结束(安全,信任等)。此外,你自己清理得比你需要的多(有点太多,你会在阅读我的答案时发现)。

我发现你的代码有第二个问题,你可能不知道。 通过在我自己的VS环境中解决该问题,我成功地渲染了Bitmaps(在IIS 7和Express以及ASP开发服务器中)。

很有可能通过在应用程序代码中重新组织一些东西,您将设法解决问题#1。所以:请查看关于问题#2的内容。

问题#2:无法同时处理和返回流

您无法返回刚刚创建的并处置的流:

public static Stream SomeMethod() {
  using (MemoryStream stream = new MemoryStream()) {
    // write something to the stream
    return stream;
  }
}

我真的不明白这段代码在ASP.NET Development Server中是如何工作的。 我试图在这里指出的问题是你的代码总是抛出一个ObjectDisposedException(无论你是将代码作为服务运行还是在交互式用户空间中运行):

Cannot access a closed stream

谁关闭了流?终止使用语句。

问题#2的可能解决方案

这个特定问题的快速解决方案(可能会占用比你预测的更多的内存)将使你的方法返回一个byte []而不是一个流。

public static byte[] SomeMethod() {
  using (MemoryStream stream = new MemoryStream()) {

    // ... create bitmap and render things ...

    // write something to the stream
    bitmap.Save(stream, ImageFormat.Png);

    return stream.ToArray();
  }
}

允许我自己对您的应用程序需求做出假设我会说其他解决方案可能会更好:

如果,您希望将这些生成的图表图片返回到&lt; img&gt; 标记回Web浏览器,您可以通过ASP.NET Generic Handler完成此操作,然后您可以将当前WebResponse 的OutputStream传递给你的绘图方法,而不是从中获取结果字节[](或流),如下所示:

在HTML中:

<img src="path/Foo.ashx" alt="chart" ... etc ... />

在应用程序中:

public class Foo : IHttpHandler {
  public void ProcessRequest(HttpContext context) {

   context.Response.ContentType = "application/octet-stream";
   Stream alreadyExistingStream = context.Response.OutputStream;

   Etc.SomeMethod(stream);       
  }
}

public class Etc {

public static void SomeMethod(Stream stream) {
  // There used to be a using here that would create a stream
    // simply because the parameter name **stream** is the same as the former local var's name
    // the instructions that do the drawing of things 
    // + saving of the resulting Bitmap **to** the stream
    // keep on compiling without any problems

    // draw things to a bitmap
    // write the bitmap to the stream
    bitmap.Save(stream, ImageFormat.Png);

    // returning stuff is not needed anymore
  // This used to be the time and place where the stream would be disposed
  // and it's resources given back to the community
}

}