2009-02-24 205 views
7

基本上我想在ASP.NET处理程序,以呈现一个简单的图片:无法呈现图像HttpContext.Response.OutputStream

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这只是“通用”。

+0

您的解决方案使用的GetBuffer(),必须你在`Response.OutputStream.Write`之后放置`Image`和`MemoryStream`对象? – Pingpong 2017-08-18 00:23:27

回答

6

作者确实需要寻求在流中正确写入。

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

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

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

+0

好的,谢谢! MSDN对GetBuffer()的说法几乎相同: http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx – Serguei 2009-02-26 18:25:54

1

我相信问题是,Response.OutputStream不支持寻求。为了保存PNG(或JPEG),图像对象需要能够非顺序地写入输出。如果我没有记错的话,如果将图像保存为BMP,则该图像可以工作,因为可以在不查找流的情况下写入图像格式。

+0

我试过,但实际结果是一样的。 – Serguei 2009-02-24 18:31:08

0

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

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

3

Image.Save(MemoryStream stream)确实需要可以查找的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