Measuring the Size of Uploaded Images

In an earlier snippet I showed you how to measure the size of an image on disk. In a more recent post I explained how to work with an in-memory representation of an uploaded file and attach it to an e-mail message.

If you combine the two concepts you end up with a solution that allows you to check the dimensions of an uploaded file, so you can reject it if it doesn't have the correct dimensions before you save it to disk.

Introduction

It's not uncommon that you want to check the dimensions of an image that a user uploads to your web site. For example, you may want to check the size of an uploaded banner in an advertising web site, or check the size of an image that is shown in a news article. You could, of course, just allow any uploaded image and resize it on the fly, but in many cases you end up with distorted images because they have been resized with incorrect proportions. So, depending on your requirements, it can be a good idea to check the dimensions of the image, and reject the uploaded file if it doesn't meet your requirements. By checking the dimensions of the uploaded file before it's saved to disk, you save yourself the trouble from deleting the temporary image when it doesn't meet the specifications.

Fortunately, this is all quite easy to accomplish. The code download at the end of the article contains a small web site with a fully working example in both VB.NET and C#. The web site contains a web.config file with two appSettings keys for the required dimensions:

<appSettings>
  <add key="RequiredHeight" value="184"/>
  <add key="RequiredWidth" value="370"/>
</appSettings>		  

The values for the height and width are arbitrary in the sample application and can easily be changed to meet your requirements. These values are read and stored in private variables in the page when it is posted back (that is, when a file has been uploaded) with the following code (I am showing the C# version here, but you can find similar code for VB.NET in the demo application which you can download at the end of this article):

if (Page.IsPostBack)
{
  height = Convert.ToInt32(
       ConfigurationManager.AppSettings.Get("RequiredHeight"));
  width = Convert.ToInt32(
       ConfigurationManager.AppSettings.Get("RequiredWidth"));
}

These values are used to validate the dimensions of the image, which is shown later.

The markup of the demo page contains an <asp:FileUpload> control, a Button and a number of validator controls, used to ensure the user has selected a file and to provide feedback about the uploaded file and whether it meets the validation rules.

When the user has selected a file and clicked the Upload button, the following code is triggered:

Page.Validate();
if (Page.IsValid)
{
  if (FileUpload1.HasFile)
  {
    string extension = Path.GetExtension(FileUpload1.PostedFile.FileName);
    switch (extension.ToLower())
    {
      // Only allow uploads that look like images.
      case ".jpg":
      case ".jpeg":
      case ".gif":
      case ".bmp":
        try
        {
          if (ValidateFileDimensions())
          {
            string fileName = Path.GetFileName(
                FileUpload1.PostedFile.FileName);
            string saveAsName = Path.Combine(
                Server.MapPath("~/Uploads/"), fileName);
            FileUpload1.PostedFile.SaveAs(saveAsName);
            lblSucces.Visible = true;
          }
          else
          {
            valInvalidDimensions.IsValid = false;
            valInvalidDimensions.ErrorMessage = 
              String.Format(valInvalidDimensions.ErrorMessage, 
              height, width);
          }
        }
        catch
        {
          // Unable to read the file dimensions. 
          // The uploaded file is probably not an image.
          valInvalidFile.IsValid = false;
        }
        break;

      default: // The uploaded file has an incorrect extension
        valInvalidFile.IsValid = false;
        break;
    }
  }
}  

The code first checks if a file has been uploaded by checking the HasFile property of the FileUpload control. It then proceeds to check the extension of the uploaded file to see if it's an image or not. You can add or remove case blocks to the switch statement to change the type of files that your users are allowed to upload.

When the uploaded file looks like an image, the method ValidateFileDimensions (shown later) is called to check the dimensions of the uploaded image. If this method returns true, the image meets the specifications and it is saved to disk using the SaveAs method of the PostedFile. If the image has incorrect dimensions, the CustomValidator called valInvalidDimensions is shown to the user. Notice how String.Format is used to embed the required height and width into the ErrorMessage of the validator. In the markup, the ErrorMessage property contains two placeholders that are replaced by String.Format to inject the dimensions in the message:

<asp:CustomValidator 
  ID="valInvalidDimensions" 
  runat="server" 
  ErrorMessage="The image you uploaded has incorrect dimensions. 
    Please select a file with a height of {0}px and a width of {1}px." 
  Display="Dynamic" 
  EnableViewState="false">
</asp:CustomValidator>  

The most important part of the sample page is the ValidateFileDimensions method which is remarkably simple:

public bool ValidateFileDimensions()
{
using (System.Drawing.Image myImage =
System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream))
{
return (myImage.Height == height && myImage.Width == width);
}
}

This code creates a new Image object by calling Image.FromStream and passing it the InputStream property of the PostedFile. This creates an in-memory representation of the image which exposes properties like Height and Width. Those are then used to check the dimensions of the image against the required height and width fields. The method returns true when the image has the exact same dimensions as specified in the private height and width fields. Otherwise it returns false. When the uploaded file doesn't contain a valid image at all, Image.FromStream raises an exception which is handled in the calling code.

The code contains a using block to ensure that the image is disposed of as soon as it's not needed anymore.

Notice I am prefixing the Image class with its full System.Drawing namespace to avoid name collisions with the Image class from the System.Web.UI.WebControls namespace which is imported by default.

Summary

Checking the dimensions of an image that is uploaded by your users is useful in many situations. Being able to check the image before it's even saved to disk is even better, as it frees you from deleting invalid images after they have been uploaded. With the code from this article you can now perform the validation while the image is still in memory and only save it to disk when it meets your requirements.

Further Reading

Download Files

Source Code for this Article The download contains a working example in both C# and VB.NET.

Where to Next?

Wonder where to go next? You can post a comment on this article.

Doc ID 417
Full URL https://imar.spaanjaars.com/417/measuring-the-size-of-uploaded-images
Short cut https://imar.spaanjaars.com/417/
Written by Imar Spaanjaars
Date Posted 01/20/2007 15:17
Listened to when writing This Mess We're In by P.J. Harvey (Track 7 from the album: Stories From The City, Stories From The Sea)

Comments

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the Doc ID of the document.

(Plain text only; no HTML or code that looks like HTML or XML. In other words, don't use < and >. Also no links allowed.