使用C# HttpHandler webservice创建PNG图像

13

我想要能够使用C#的Web服务创建一个简单的PNG图像,例如一个红色的正方形,然后通过一个<img src="myws.ashx?x=100> HTML元素调用生成的图像。

一些示例HTML:

<hmtl><body>
     <img src="http://mysite.com/webservice/rectangle.ashx?size=100">
</body></html>

有没有人能够拼凑出一个简单(可行的)C#类来帮助我开始?一旦启动,我相信我可以完成它真正要做的事情。

  • 最终目标是创建一个简单的红/黄/绿(RAG)嵌入式状态标记,用于显示性能指标等数据驱动的网页*
  • 我希望它使用PNG图像,因为我预计将来会使用透明度*
  • 请使用ASP.NET 2.0 C#解决方案...(我还没有生产3.5的系统)

tia

解决方案

rectangle.html

<html>
<head></head>
<body>
    <img src="rectangle.ashx" height="100" width="200">
</body>
</html>

矩形.ashx

<%@ WebHandler Language="C#" Class="ImageHandler" %>

矩形.cs

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

public class ImageHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        int width = 600; //int.Parse(context.Request.QueryString["width"]);
        int height = 400; //int.Parse(context.Request.QueryString["height"]);

        Bitmap bitmap = new Bitmap(width,height);

        Graphics g = Graphics.FromImage( (Image) bitmap );
        g.FillRectangle( Brushes.Red, 0f, 0f, bitmap.Width, bitmap.Height );    // fill the entire bitmap with a red rectangle

        MemoryStream mem = new MemoryStream();
        bitmap.Save(mem,ImageFormat.Png);

        byte[] buffer = mem.ToArray();

        context.Response.ContentType = "image/png";
        context.Response.BinaryWrite(buffer);
        context.Response.Flush();
    }

    public bool IsReusable {
        get {return false;}
    }
}

你能让一个HTTP处理程序返回一张图片吗?比如说一个位图图像或者一个字节数组缓冲区,返回到一个C#方法(代码后台文件)中被调用的地方?如果我听起来很愚蠢,请原谅,因为我是新手HTTP处理程序。 - zack
@YP,看到已经接受的答案了吗?否则我不明白你的意思,坦率地说,我也不知道该怎么做。我的C#水平一般! - Guy
@guy 感谢您发布解决方案 - 对我帮助很大! - Chris B
6个回答

21

Web服务,特别是SOAP,期望传入一个包含调用细节的XML封套。你最好使用 HttpHandler

类似于这样:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

public class ImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        int width = int.Parse(context.Request.QueryString["width"]);
        int height = int.Parse(context.Request.QueryString["height"]);

        using (Bitmap bitmap = new Bitmap(width,height)) {

            ...

            using (MemoryStream mem = new MemoryStream()) {
                bitmap.Save(mem,ImageFormat.Png);
                mem.Seek(0,SeekOrigin.Begin);

                context.Response.ContentType = "image/png";

                mem.CopyTo(context.Response.OutputStream,4096);
                context.Response.Flush();
            }
        }
    }

}

这当然非常粗略。你会称其为:

<img src="myhandler.ashx?width=10&height=10"/>

2
是的,我错过了一些部分,如果您进入“添加新项”对话框,它会为您正确创建一个HttpHandler,或者将鼠标悬停在IHttpHandler上并选择“实现此接口”。它类似于:public bool IsReusable { get { return true; } } - Lloyd
谢谢 - 明白了!另外,Response.ContentType和ImageFormat.Png有一个小错别字。现在只需要让它画点什么... - Guy
1
对于缓存,我看到你提到可以使用HttpRuntime.Cache,只需将MemoryStream的byte[]返回值转储到其中即可。 - Lloyd
终于搞定了!使用context.Response.BinaryWrite(buffer); Lloyd,如果你能纠正答案中的错别字,那么你就可以得到积分!!! - Guy
@Lloyd:你能让http处理程序返回一张图片吗?比如一个位图图像或一个字节数组缓冲区到C#方法(代码后台文件),然后从那里调用它?如果我听起来很傻,我很抱歉,但我是新手Http处理程序。 - zack
以上示例返回一张图片。 - Lloyd

3

网络服务不适合这个任务。它会返回特定格式(通常是SOAP)的消息,因此不能是图片。

请使用普通的网页表单,除了@page指令之外删除所有标记。使用BinaryWrite方法将图像数据写入响应流中。

例如:

byte[] imageData;
using (Bitmap image = new Bitmap(10,10)) {
   using (Graphics g = Graphics.FromImage(image)) {
      g.Clear(Color.Red);
   }
   using (MemoryStream m = new MemoryStream()) {
      image.Save(m, ImageFormat.Png);
      imageData = m.ToArray();
   }
}
Response.ContentType = "image/png";
Response.BinaryWrite(imageData);

我会对此进行唯一的更改,即使用通用处理程序(.ashx文件)。没有必要使用所有页面(.aspx)开销。 - Keltex
实际上,通过网络服务可以实现这一点;我用PDF文件来做。关键是将其作为字节数组返回,然后在另一端重新构建它,并使用适当的ContentType进行输出。 - Adam V
@Adam V:那么您只将 Web 服务用作 Web 页面的后端。您不能直接使用来自 Web 服务的响应,就像 Guy 所要求的那样。 - Guffa

2

哈!我已经研究了你的问题一个小时了。如果我能把一些“简单的东西”搞定,那么我相信即使是我这个C#小白也能完成它。 - Guy

1

有另一种方法可以实现动态图像的服务。

namespace MyApp
{
    [ServiceContract]
    public interface IMyService
    {
        [WebGet(UriTemplate = "Image.png")]
        [OperationContract]
        Stream ShowImage();
    }
}

对于实施:

public Stream ShowImage()
{
    Bitmap image = new Bitmap(@"C:\Image.png");
    Image image2 = new Bitmap(125, 125);

    using (Graphics graphics = Graphics.FromImage(image2))
    {
           graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
           graphics.SmoothingMode = SmoothingMode.HighQuality;
           graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
           graphics.CompositingQuality = CompositingQuality.HighQuality;
           graphics.DrawImage(image, 0, 0, 125, 125);
    }

    MemoryStream imageAsMemoryStream = new MemoryStream();
    image2.Save(imageAsMemoryStream, ImageFormat.Png);
    imageAsMemoryStream.Position = 0;
    return imageAsMemoryStream;
}

将服务作为常规的 WCF 服务启动,并将服务添加到您的 app.config 中

(WebService = new WebServiceHost(typeof(MyService))).Open();

您可以传递参数以使其更具动态性。


0

这取决于人们如何看待 Web 服务。使用 C# Web API 通过多部分 MIME 编码 perfectly 可以返回二进制(图像)。它已经实现过了。首先可以参考这个链接:http://en.wikipedia.org/wiki/MIME在 C# 中做这个并不是特别具有挑战性。 - Demi
1
"这取决于一个人如何看待Web服务。" << 我同意。 - NinethSense
或者按照Guffa的帖子中提到的,直接返回二进制。 :-) - Demi
抱歉,也许我的术语不准确(或者对于技术社区来说不够准确)。我理解.asmx是用来返回XML内容的?我之前从未听说过ashx。 - Guy
1
@Guy,asmx是Web服务,ashx是处理程序。Ashx与aspx几乎相同。它实现了IHttpHandler。请查看此链接以获取更多详细信息:https://dev59.com/NHRB5IYBdhLWcg3wc280。它可以帮助您生成图像。 - NinethSense

0

此外,根据您实施的方式,需要注意您可能会遭受DOS攻击。生成图像不是最友好的处理器操作。请确保设置某些身份验证和/或缓存机制,以帮助缓解这种潜在痛点。


仅限内部/内网使用,但必须实现缓存!谢谢。 - Guy

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