无法将图像渲染到HttpContext.Response.OutputStream

时间:2009-02-24 17:45:42

标签: c# asp.net gdi+ system.drawing

基本上我试图在ASP.NET处理程序中渲染一个简单的图像:

public void ProcessRequest (HttpContext context)
{
    Bitmap image = new Bitmap(16, 16);
    Graphics graph = Graphics.FromImage(image);

    graph.FillEllipse(Brushes.Green, 0, 0, 16, 16);

    context.Response.ContentType = "image/png";
    image.Save(context.Response.OutputStream, ImageFormat.Png);
}

但我得到以下例外:

System.Runtime.InteropServices.ExternalException: A generic error
occurred in GDI+.
    at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder,
    EncoderParameters encoderParams)

解决方案是使用它而不是将图像写入OutputStream:

MemoryStream temp = new MemoryStream();
image.Save(temp, ImageFormat.Png);
byte[] buffer = temp.GetBuffer();
context.Response.OutputStream.Write(buffer, 0, buffer.Length);

所以我只是好奇为什么第一个变种有问题?

编辑:HRESULT是80004005,只是“通用”。

4 个答案:

答案 0 :(得分:6)

作者确实需要设法正确地写入流。

但是在上一个源代码中,请确保使用MemoryStream.ToArray()来获取正确的数据,或者,如果您不想复制数据,请使用MemoryStream.GetBuffer()和MemoryStream.Length以及不是返回数组的长度。

GetBuffer将返回MemoryStream使用的内部缓冲区,其长度通常大于已写入流的数据的长度。

这将避免你在流的末尾发送垃圾,而不是搞乱一些不能容忍尾随垃圾的严格图像解码器。 (并传输较少的数据......)

答案 1 :(得分:4)

Image.Save(MemoryStream流)确实需要一个可以寻找的MemoryStream对象。 context.Response.OutputStream是仅向前的,不支持搜索,因此您需要一个中间流。但是,您不需要字节数组缓冲区。您可以直接从临时内存流写入context.Response.OutputStream:

/// <summary>
/// Sends a given image to the client browser as a PNG encoded image.
/// </summary>
/// <param name="image">The image object to send.</param>
private void SendImage(Image image)
{
    // Get the PNG image codec
    ImageCodecInfo codec = GetCodec("image/png");

    // Configure to encode at high quality
    using (EncoderParameters ep = new EncoderParameters())
    {
        ep.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

        // Encode the image
        using (MemoryStream ms = new MemoryStream())
        {
            image.Save(ms, codec, ep);

            // Send the encoded image to the browser
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ContentType = "image/png";
            ms.WriteTo(HttpContext.Current.Response.OutputStream);
        }
    }
}

这里有一个功能齐全的代码示例:

Auto-Generate Anti-Aliased Text Images with ASP.NET

答案 2 :(得分:1)

我认为问题在于Response.OutputStream不支持搜索。为了保存PNG(或JPEG),图像对象需要能够非顺序地写入输出。如果我没记错的话,如果您将图像保存为BMP,那将会有效,因为可以在不搜索流的情况下编写图像格式。

答案 3 :(得分:0)

好的我使用Stream的包装器(实现Stream并将调用传递给底层流)来确定Image.Save()调用Position和Length属性而不检查返回false的CanSeek。它还尝试将Position设置为0。

所以似乎需要一个中间缓冲区。