Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Rename, Resize, Upload Image (ASP.NET MVC)

4.74/5 (17 votes)
1 Feb 2015CPOL 114.9K   4.5K  
How to upload, rename and resize in MVC

The Problem

  1. File overwrite, if filename already exists
  2. Image Resizing

The Solution

I created a Class called "ImageUpload" that solves the above problems. The Class renames the filename with "item_counter_filename". If the name already exists in the directory, it will increment the counter by 1 until an available name is found (this is done recursively). Afterwards, the Class will resize the image to your needs. If you set the Width and Height, then you will be forcing a non proportional resize, this might cause distortion. However, if you set the Width or Height, then you will be resizing the image proportionally.

The method that will do all the work is called "RenameUploadFile". This method returns a POCO object called "ImageResult".

C#
public class ImageResult
{
    public bool Success { get; set; }
    public string ImageName { get; set; }
    public string ErrorMessage { get; set; }
}

If the upload was successful, then the Success property will be set to true. Then you can save ImageName which holds the final filename that has been uploaded to the directory. If Success was false, ErrorMessage will contain the Exception message.

Show Me the Code Already!

Index.cshtml

HTML
<div class="row">
    <div class="col-md-12">
        <h2>Rename, Resize, and Upload Image</h2>
        @if (ViewBag.Error != null)
        {
            <h4 style="color:red">@ViewBag.Error</h4>
        }
        @using (Html.BeginForm("Index", "Home", 
        FormMethod.Post, new { enctype = "multipart/form-data" }))
        {
            <div>Upload Image</div>
            <input type="file" name="avatar" />
            <input type="submit" value="upload" />
        }
    </div>
</div>

HomeController.cs

C#
[HttpPost]
public ActionResult Index(FormCollection formCollection)
{
    foreach (string item in Request.Files)
    {
        HttpPostedFileBase file = Request.Files[item] as HttpPostedFileBase;
        if (file.ContentLength == 0)
            continue;
        if (file.ContentLength > 0)
        {
            // width + height will force size, care for distortion
            //Exmaple: ImageUpload imageUpload = new ImageUpload { Width = 800, Height = 700 };

            // height will increase the width proportionally
            //Example: ImageUpload imageUpload = new ImageUpload { Height= 600 };

            // width will increase the height proportionally
            ImageUpload imageUpload = new ImageUpload { Width= 600 };

            // rename, resize, and upload
            //return object that contains {bool Success,string ErrorMessage,string ImageName}
            ImageResult imageResult = imageUpload.RenameUploadFile(file);
            if (imageResult.Success)
            {
                //TODO: write the filename to the db
                Console.WriteLine(imageResult.ImageName);
            }
            else
            {
                // use imageResult.ErrorMessage to show the error
                ViewBag.Error = imageResult.ErrorMessage;
            }
        }
    }

  return View();
}

ImageUpload.cs

C#
public class ImageUpload
    {
        // set default size here
        public int Width { get; set; }
        
        public int Height { get; set; }

        // folder for the upload, you can put this in the web.config
        private readonly string UploadPath = "~/Images/Items/";

        public ImageResult RenameUploadFile(HttpPostedFileBase file, Int32 counter = 0)
        {
            var fileName = Path.GetFileName(file.FileName);

            string prepend = "item_";
            string finalFileName = prepend + ((counter).ToString()) + "_" + fileName;
            if (System.IO.File.Exists
                (HttpContext.Current.Request.MapPath(UploadPath + finalFileName)))
            {
                //file exists => add country try again
                return RenameUploadFile(file, ++counter);
            }
            //file doesn't exist, upload item but validate first
            return UploadFile(file, finalFileName);
        }

        private ImageResult UploadFile(HttpPostedFileBase file, string fileName)
        {
            ImageResult imageResult = new ImageResult { Success = true, ErrorMessage = null };

            var path =
          Path.Combine(HttpContext.Current.Request.MapPath(UploadPath), fileName);
            string extension = Path.GetExtension(file.FileName);

            //make sure the file is valid
            if (!ValidateExtension(extension))
            {
                imageResult.Success = false;
                imageResult.ErrorMessage = "Invalid Extension";
                return imageResult;
            }

            try
            {
                file.SaveAs(path);

                Image imgOriginal = Image.FromFile(path);

                //pass in whatever value you want
                Image imgActual = Scale(imgOriginal);
                imgOriginal.Dispose();
                imgActual.Save(path);
                imgActual.Dispose();
                
                imageResult.ImageName = fileName;

                return imageResult;
            }
            catch (Exception ex)
            {
                // you might NOT want to show the exception error for the user
                // this is generally logging or testing

                imageResult.Success = false;
                imageResult.ErrorMessage = ex.Message;
                return imageResult;
            }
        }

      private bool ValidateExtension(string extension)
        {
            extension = extension.ToLower();
            switch (extension)
            {
                case ".jpg":
                    return true;
                case ".png":
                    return true;
                case ".gif":
                    return true;
                case ".jpeg":
                    return true;
                default:
                    return false;
            }
        }

        private Image Scale(Image imgPhoto)
        {
            float sourceWidth = imgPhoto.Width;
            float sourceHeight = imgPhoto.Height;
            float destHeight = 0;
            float destWidth = 0;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

           // force resize, might distort image
            if (Width != 0 && Height != 0)
            {
                destWidth = Width;
                destHeight = Height;
            }
            // change size proportially depending on width or height
            else if (Height != 0)
            {
                destWidth = (float)(Height * sourceWidth) / sourceHeight;
                destHeight = Height;
            }
            else
            {
                destWidth = Width;
                destHeight = (float)(sourceHeight * Width / sourceWidth);
            }

            Bitmap bmPhoto = new Bitmap((int)destWidth, (int)destHeight,
                                        PixelFormat.Format32bppPArgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, (int)destWidth, (int)destHeight),
                new Rectangle(sourceX, sourceY, (int)sourceWidth, (int)sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();

            return bmPhoto;
        }
    }

ImageResult.cs

C#
public class ImageResult
{
    public bool Success { get; set; }
    public string ImageName { get; set; }
    public string ErrorMessage { get; set; }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)