使用ASP.NET服务器提供图像

时间:2014-10-15 12:42:13

标签: c# asp.net web

我是ASP.NET新手,我试图创建一个服务器应用程序,它根据客户端的HTTP请求返回存储的图像。我不确定从哪里开始。

我对在服务器和客户端之间建立连接的过程非常有信心,但我不确定如何处理HTTP请求和响应。我想我必须使用System.Web.HttpRequest和System.Web.HttpResponse。

用例可能如下所示:

客户端向服务器发送一个URL,如服务器然后处理的http://10.10.180.10:8080/Images/image.jpg,如果URL等于/Images/image.jpg,它会通过某种输出流返回图像。

我很难找到如何开始这个的好指南。我在ASP.NET中找到的所有东西都是为了建立一个网站,但我只想创建一个服务器应用程序,因为我已经有了客户端。

1 个答案:

答案 0 :(得分:4)

如果您不需要任何特定功能,那么IIS可以很好地从文件系统提供图像。您甚至可以在其上配置基于ASP.NET的身份验证,并根据角色限制访问。

如果您确实需要特定的功能(比如添加水印或从数据库中获取图像),那么您需要使用的是HttpHandler。这基本上是一个通过名为ProcessRequest的方法处理HTTP请求的类。在此方法中,您可以编写适当的代码来获取图像,如果需要,可以使用Response对象将字节写入客户端。如果您需要高可伸缩性,建议使用异步HttpHandler。

这是我们在现实世界项目中使用的完整处理程序,用于通过缓存支持从数据库提供图像。我很确定它并不完美和普遍,但它对我们有用。

using OurProject.Models.Entities;
using System;
using System.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace OurProject
{
    public class PhotoHandler : HttpTaskAsyncHandler
    {
        private const double CacheDateEpsilonSeconds = 1;
        public override bool IsReusable
        {
            get
            {
                //the handler does not store any state so the object can be reused
                return true;
            }
        }

        public override async Task ProcessRequestAsync(HttpContext context)
        {
            //get the id of the photo object
            int photoID;
            if (!Int32.TryParse(context.Request.QueryString["ID"], out photoID))
            {
                context.Response.StatusCode = 400;
                return;
            }

            var dataContext = new DataContext();

            //retrieve the object metadata from the database. Not that the call is async so it does not block the thread while waiting for the database to respond
            PhotoInfo photoInfo = await dataContext.PhotoInfos.SingleOrDefaultAsync(pi => pi.BusinessCardID == photoID);

            //if the object is not found return the appropriate status code
            if (photoInfo == null)
            {
                context.Response.StatusCode = 404;
                return;
            }

            DateTime clientLastModified;

            //check if the image has been modified since it was last served
            //if not return 304 status code
            if (DateTime.TryParse(context.Request.Headers["If-Modified-Since"], out clientLastModified) &&
                clientLastModified.AddSeconds(CacheDateEpsilonSeconds) >= photoInfo.LastModifiedDate)
            {
                context.Response.StatusCode = 304;
                context.Response.StatusDescription = "Not Modified";
                return;
            }

            //set various cache options
            context.Response.Cache.SetCacheability(HttpCacheability.Private);
            context.Response.Cache.VaryByParams["d"] = true;
            context.Response.Cache.SetLastModified(photoInfo.LastModifiedDate);
            context.Response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0));
            context.Response.Cache.SetOmitVaryStar(true);
            context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(365));
            context.Response.Cache.SetValidUntilExpires(true);

            //Get the actual file data. Again note the async IO call
            PhotoFile file = await dataContext.PhotoFiles.SingleAsync(pf => pf.BusinessCardID == photoID);

            //serve the image with the appropriate MIME type. In this case the MIME type is determined when saving in the database
            context.Response.ContentType = photoInfo.MimeType;
            context.Response.BinaryWrite(file.PhotoData);

        }
    }
}