简体   繁体   中英

Using ASP.NET server to serve images

I'm new to ASP.NET and I'm trying to make a server application which returns a stored image upon a HTTP request from a client. I'm just not exactly sure where to start.

I'm pretty confident in the process of establishing the connection between the server and the client, but I'm not sure how to handle the HTTP request and response. I imagine I have to use the System.Web.HttpRequest and System.Web.HttpResponse.

A use case could be like the following:

A client send a URL to the server like http://10.10.180.10:8080/Images/image.jpg which the server then handles and if the URL equals /Images/image.jpg it returns the image through some kind of output stream.

I've had trouble finding a good guide on how to get started with this. Everything I've found with ASP.NET has been with the intention of making a website, but I just want to make a server application as I already have the client.

If you do not need any specific functionality then IIS serves images from the file system just fine. You can even configure ASP.NET based authentication on top of it and restrict the access based on roles.

If you do need a specific functionality (say add watermark or get the images from a database) then what you need to use is an HttpHandler. This is basically a class that processes an HTTP request via a method called ProcessRequest. In this method you write the appropriate code to get the image, manipulate it if you need to and use the Response object to write the bytes to the client. If you need high scalability it is advisable to use asynchronous HttpHandler.

Here is a complete handler we use in a real world project for serving images from the database with caching support. I am pretty sure it is not perfect and universal but it works for us.

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);

        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM