Please see the upload code below. the method is called within a try, catch. If the code for the image utilities is needed, just say. Basically, everything is handled in raw bytes and then stored to the DB. I currently render images as base 64 but am moving towards using the bottom snippet in web api.
My main thoughts are:
- The image is uploaded in raw bytes. While it could contain a virus it wouldn't run
- The server has a max file size set, and prior to this method the user is authenticated, and are checked they are not concurrently downloading any other files (one at a time) with a max upload of 100 images an hour. This would, I hope, stop a specific image DoS.
- Because the image is modified to be a certain size (100 x 100) then if it's not a valid image type this would throw an exception and everything is binned
- I could add a white list on file extensions before this if you can see any potential issues?
I believe Image.FromStream is safe from an overflow attack
public string StoreProfileImage(ImageViewModel model, string userId) { var postedImg = model.Image; var image = Image.FromStream(postedImg.InputStream, true, true); if (image != null) { Rectangle rect = new Rectangle(); rect.X = (int)Math.Floor(model.x / model.scale); rect.Y = (int)Math.Floor(model.y / model.scale); rect.Width = (int)Math.Floor(model.width / model.scale); rect.Height = (int)Math.Floor(model.height / model.scale); // crop the image var croppedImg = ImageUtilities.CropImage(image, rect.Height, rect.Width, rect.X, rect.Y); // resize to max pic size var resizedImg = ImageUtilities.ResizeImage(100, 100, croppedImg); // convert to bytes byte[] imageData = ImageUtilities.ImageToByteArray(resizedImg); using (var db = new DbContext()) { var userImage = new UserImage { ImageBytes = imageData, ImageName = postedImg.FileName, UserId = userId, IsProfileImage = true }; // add new users image db.UserImage.Add(userImage); db.SaveChanges(); } return ImageUtilities.BytesToBase64(imageData); } return null; }
Rendering snippet
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(image.ImageBytes);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return result;