Skip to main content Skip to footer

Uploading photos with MVC

There are many articles online talking about MVC, but not many showing how to upload files. In a project I'm working on I need to have my users upload photographs and wanted them to be able to preview the photo before submitting it. Here's a screen shot of what I'm talking about.

image

The application allows the user to select a photo, which is then previewed. The user can then add a caption and description of the photo. During this first round the Save button is bound to the following jQuery script:

1: function uploadMemberPhoto(elem) {

2: var $elem = $(elem);

3: $("div.memberPhotoUploader").fadeIn(500);

4: var $form = $elem.parents("form");

5: $form.attr("action", "/MemberPhotos/Uploaded");

6: $elem.fadeOut(500, function () { $form[0].submit(); });

7: }

which sets the action of the form to "/MemberPhotos/Uploaded", then submits the form. The Controller action "Uploaded" handles the processing of the image.

1: public ActionResult Uploaded(HttpPostedFileBase file, FormCollection formCollection)

2: {

3: var memberPhoto = _photoHelpers.UploadMemberPhoto(file, formCollection);

4: return View("UploadedPhoto");

5: }

_photoHelpers is a helper class which does the processing of the image

1: public MemberPhoto UploadMemberPhoto(HttpPostedFileBase file, FormCollection collection)

2: {

3: var memberPhoto = new MemberPhoto();

4: try

5: {

6: if(file.ContentLength > 0)

7: {

8: var member = _repo.Get(int.Parse(collection["memberId"]));

9: var photoCaption = collection["memberPhotoCaption"];

10: var photoDescription = collection["memberPhotoDescription"];

11: var serverPath = HttpContext.Current.Server.MapPath(

12: ConfigurationManager.AppSettings["memberAvatarPath"]);

13: var memberFolder = GetMemberImageFolder(member);

14: var imagePath = serverPath memberFolder;

15:

16: if (!Directory.Exists(imagePath))

17: Directory.CreateDirectory(imagePath);

18:

19: bool success = ImageHelpers.ProcessMemberPhotoUpload(file, imagePath);

20: if(success) // insert the record

21: {

22: memberPhoto.MemberId = member.Id;

23: memberPhoto.PhotoUrl = file.FileName;

24: memberPhoto.PhotoCaption = photoCaption;

25: memberPhoto.PhotoDescription = photoDescription;

26: memberPhoto.IsApproved = false;

27: memberPhoto.IsVisible = true;

28: memberPhoto.CreateBy = member.Email;

29: memberPhoto.CreateDate = DateTime.Now;

30: memberPhoto.ModifyBy = member.Email;

31: memberPhoto.ModifyDate = DateTime.Now;

32: memberPhoto.Mode = ImageHelpers.ImageMode(file);

33: _repo.Create(memberPhoto);

34: }

35: }

36: }

37: catch (Exception ex)

38: {

39: memberPhoto = null;

40: }

41: return memberPhoto;

42: }

1: public bool ProcessMemberPhotoUpload(HttpPostedFileBase img, string fPath)

2: {

3: fPath = fPath.Replace("\\\", "\\");

4: var resizedImage = ResizeImage(img, new Size(640, 480));

5: var status = SaveImage(resizedImage, fPath, img.FileName);

6:

7: var thumbNail = ResizeImage(img, new Size(102, 77));

8: status = SaveImage(thumbNail, fPath, "thmb_" img.FileName);

9:

10: var largeThumb = ResizeImage(img, new Size(400, 600));

11: status = SaveImage(largeThumb, fPath, "lgthmb_" img.FileName);

12: return status;

13: }

The rest of the methods used in the helper class are here

1: private static Image ResizeImage(HttpPostedFileBase img, Size size)

2: {

3: var oImage = Image.FromStream(img.InputStream);

4: var sWidth = oImage.Width;

5: var sHeight = oImage.Height;

6:

7: if(size.Width >= oImage.Width && size.Height >= oImage.Height)

8: return (Image) oImage;

9:

10: float nPercent = 0;

11: float nPercentW = 0;

12: float nPercentH = 0;

13:

14: nPercentW = ((float) size.Width/(float) sWidth);

15: nPercentH = ((float) size.Height/(float) sHeight);

16:

17: if (nPercentH < nPercentW)

18: nPercent = nPercentH;

19: else

20: nPercent = nPercentW;

21:

22: int dWidth = (int) (sWidth*nPercent);

23: int dHeight = (int) (sHeight*nPercent);

24:

25: Bitmap b = new Bitmap(dWidth, dHeight);

26: Graphics g = Graphics.FromImage((Image) b);

27: g.InterpolationMode = InterpolationMode.HighQualityBicubic;

28: g.DrawImage(oImage, 0, 0, dWidth, dHeight);

29: g.Dispose();

30: return (Image) b;

31: }

32:

33: private static bool SaveImage(Image img, string savePath, string fileName)

34: {

35: var status = true;

36: try

37: {

38: var newPath = new StringBuilder(savePath).Append(fileName);

39: File.Delete(newPath.ToString());

40: img.Save(newPath.ToString(), img.RawFormat);

41: }

42: catch (Exception)

43: {

44: status = false;

45: }

46: return status;

47: }

48:

49: public string ImageMode(HttpPostedFileBase img)

50: {

51: var oImage = Image.FromStream(img.InputStream);

52: var mode = "landscape";

53: if (oImage.Width < oImage.Height) mode = "portrait";

54: oImage.Dispose();

55: return mode;

56: }

In this particular application, all photos uploaded need to be approved, so after the photo is uploaded, the page refreshes, keeping the original form action of "/MemberPhotos/UpdatePhoto"

image

1: public ActionResult UpdatePhoto(MemberPhoto photo)

2: {

3: photo.ModifyBy = User.Identity.Name;

4: photo.ModifyDate = DateTime.Now;

5: _repo.Edit(photo);

6: }

You may be wondering how the image is previewed. I found this article at, http: //weblogs.asp.net/imranbaloch/archive/2010/04/03/image-preview-in-asp-net-mvc.aspx and modified it a bit for my needs. This bit of javascript works like a champ.

1: function ChangeImage(fileId, imageId) {

2: $("div.memberPhotoUploader").fadeIn(500);

3: $("#form1").ajaxSubmit({ success: function (responseText) {

4: if (isImage(responseText)) {

5: var d = new Date();

6: $(imageId)[0].src = "/ImagePreview/ImageLoad?a=" d.getTime();

7: $(imageId).show();

8: $("input#uploadButton").removeClass("btnSaveDisabled")

9: .addClass("btnSaveEnabled").removeAttr("disabled").click(function () {

10: uploadMemberPhoto(this);

11: }); ;

12: } else {

13: $(imageId).hide();

14: $("div.imageTypeNotice").show();

15: }

16: $("div.memberPhotoUploader").fadeOut(500);

17: }

18: });

19: }

Happy programming from ComponentOne

James

MESCIUS inc.

comments powered by Disqus