1

I have an asp.net mvc 5 app with a database that stores photos. I'm trying to read the photo and resize it for display in a Staff profile.

I'm fairly new to both asp.net mvc and c#

I setup the following controller but am not getting an image display when I use a link to the controller in an img tag.

Any help would be appreciated.

public ActionResult Index(int id)
    {
        Staff staff = db.StaffList.Find(id);
        if (staff.Photo != null)
        {
            var img = new WebImage(staff.Photo);
            img.Resize(100, 100, true, true);
            var imgBytes = img.GetBytes();

            return File(imgBytes, "image/" + img.ImageFormat);
        }
        else
        {
            return null;
        }
    }
1
  • your markup will have to be set up properly to show it in the appropriate size. html / css have more bearing on the size of the image displayed than the server does. Commented Apr 8, 2015 at 20:52

2 Answers 2

1

Looking around it seems there's a lot of dissatisfaction with the WebImage class and it has a few prominent bugs. I settled on using a nuget package called ImageProcessor rather than trying to write my own. This seems fairly inefficient to me but I don't have a better answer right now and this isn't heavily used so I'm going with this and just moving on.

Posting it here in case anyone else is struggling with something similar.

    public ActionResult Index(int id, int? height, int? width)
    {
        int h = (height ?? 325);
        int w = (width ?? 325);

        Staff staff = db.StaffList.Find(id);
        if (staff == null)
        {
            return new HttpNotFoundResult();
        }
        if (staff.Photo != null)
        {
            Size size = new Size(w, h);
            byte[] rawImg;
            using (MemoryStream inStream = new MemoryStream(staff.Photo))
            {
                using (MemoryStream outStream = new MemoryStream())
                {
                    using (ImageFactory imageFactory = new ImageFactory())
                    {
                        imageFactory.Load(inStream)
                            .Constrain(size)
                            .Format(format)
                            .Save(outStream);
                    }
                    rawImg = outStream.ToArray();
                }
            }
            return new FileContentResult(rawImg, "image/jpeg");
        }
        else
        {
            return null;
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

0

I'm going to answer this using ImageProcessor since your own answer uses the library. Disclaimer. I'm also the author of the library.

You're really not best using an ActionResult for processing images as it will be horribly inefficient. It run's far too late in the pipeline and you will have no caching.

You're much better off installing the Imageprocessor.Web package and implementing your own version of the IImageService interface to serve your images from the database. (On that note storing images in a db unless you are using blob storage is never wise either)

Implementing the IImageService interface allows you to utilise the url api within the library with a specific prefix to identify which image service to use. For example, remote image requests are prefixed with remote.axd to tell IageProcessor.Web to excute the RemoteImageService implementation.

This has the benefit of caching your images so subsequent requests are returned from a cache rather than being reprocessed upon each request.

Here is the full implementation of the LocalFileImageService which is the default service for the library. This should be able to serve as a guide for how to implement your own service.

namespace ImageProcessor.Web.Services
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Threading.Tasks;
    using System.Web;

    using ImageProcessor.Web.Helpers;

    /// <summary>
    /// The local file image service for retrieving images from the 
    /// file system.
    /// </summary>
    public class LocalFileImageService : IImageService
    {
        /// <summary>
        /// The prefix for the given implementation.
        /// </summary>
        private string prefix = string.Empty;

        /// <summary>
        /// Gets or sets the prefix for the given implementation.
        /// <remarks>
        /// This value is used as a prefix for any image requests 
        /// that should use this service.
        /// </remarks>
        /// </summary>
        public string Prefix
        {
            get
            {
                return this.prefix;
            }

            set
            {
                this.prefix = value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the image service 
        /// requests files from
        /// the locally based file system.
        /// </summary>
        public bool IsFileLocalService
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets or sets any additional settings required by the service.
        /// </summary>
        public Dictionary<string, string> Settings { get; set; }

        /// <summary>
        /// Gets or sets the white list of <see cref="System.Uri"/>. 
        /// </summary>
        public Uri[] WhiteList { get; set; }

        /// <summary>
        /// Gets a value indicating whether the current request 
        /// passes sanitizing rules.
        /// </summary>
        /// <param name="path">
        /// The image path.
        /// </param>
        /// <returns>
        /// <c>True</c> if the request is valid; otherwise, <c>False</c>.
        /// </returns>
        public bool IsValidRequest(string path)
        {
            return ImageHelpers.IsValidImageExtension(path);
        }

        /// <summary>
        /// Gets the image using the given identifier.
        /// </summary>
        /// <param name="id">
        /// The value identifying the image to fetch.
        /// </param>
        /// <returns>
        /// The <see cref="System.Byte"/> array containing the image data.
        /// </returns>
        public async Task<byte[]> GetImage(object id)
        {
            string path = id.ToString();
            byte[] buffer;

            // Check to see if the file exists.
            // ReSharper disable once AssignNullToNotNullAttribute
            FileInfo fileInfo = new FileInfo(path);

            if (!fileInfo.Exists)
            {
                throw new HttpException(404, "No image exists at " + path);
            }

            using (FileStream file = new FileStream(path, 
                                           FileMode.Open, 
                                           FileAccess.Read, 
                                           FileShare.Read, 
                                           4096, 
                                           true))
            {
                buffer = new byte[file.Length];
                await file.ReadAsync(buffer, 0, (int)file.Length);
            }

            return buffer;
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.