Screen shot of the functionality in my app.
Introduction
I wrote a quick C# function to be used with ASP.NET which accepts the name of an ImageUpload
control, a save to path, and max height and max width parameters. It then saves the image (only JPG) file and returns true
if there is no error or false
if there is an error.
It turned out not to be as simple as it looked or sounds. With referencing through a FileUpload
, I had strange a clean up error and files not closing properly. Debugging helped me realise that you can't "use" the same FileUpload
control twice. So I have modified the code.
Background
Most articles seem to start with someone trawling around the net to find a solution to something, and then it doesn't quite work, so they make it work and add it here. This is no different.
I self taught myself Visual Basic .NET over the last 6 months, and have currently been learning C# for the last 3 weeks. So my C# isn't the cleanest... but I try. The error handling isn't perfect, but it does the job.
Using the Code
I have updated the code and made the full version available. It is in the form of a Web control, and uses a query string to keep values unique. Make sure your folder has write permissions for the ASPNET account and the SYSTEM (I think those are the two.. not too sure). Drag and drop the control into your ASP.NET page.
My code uses the DropDownBox
to select a different filename to upload. You can remove it. I am 99% sure that I dispose and close all open streams and variables properly.
Here is the full Code Behind file:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public partial class admin_Uploader2 : System.Web.UI.UserControl
{
public bool ResizeImageAndUpload(System.IO.FileStream newFile,
string folderPathAndFilenameNoExtension, double maxHeight, double maxWidth)
{
try
{
float ratio;
System.Drawing.Image thisImage = System.Drawing.Image.FromStream(newFile);
int width = (int)thisImage.Width;
int height = (int)thisImage.Height;
if (width > maxWidth)
{
ratio = (float)width / (float)maxWidth;
width = (int)(width / ratio);
height = (int)(height / ratio);
}
if (height > maxHeight)
{
ratio = (float)height / (float)maxHeight;
height = (int)(height / ratio);
width = (int)(width / ratio);
}
Bitmap outImage = new Bitmap(width, height);
Graphics outGraphics = Graphics.FromImage(outImage);
SolidBrush sb = new SolidBrush(System.Drawing.Color.White);
outGraphics.FillRectangle(sb, 0, 0, outImage.Width, outImage.Height);
outGraphics.DrawImage(thisImage, 0, 0, outImage.Width, outImage.Height);
sb.Dispose();
outGraphics.Dispose();
thisImage.Dispose();
outImage.Save(Server.MapPath(folderPathAndFilenameNoExtension + ".jpg"),
System.Drawing.Imaging.ImageFormat.Jpeg);
outImage.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
protected void ButtonUpload_Click(object sender, EventArgs e)
{
string Id = Request.QueryString["id"];
string filePath = "~\\Image_Upload\\" + Id + "-" +
DropDownListImage.SelectedValue.ToString();
string thumbPath = "~\\Image_Upload\\" + Id + "-" +
DropDownListImage.SelectedValue.ToString() + "_thumb";
// Check that there is a file
if (fileUploader.PostedFile != null)
{
// Check file size (mustn't be 0)
HttpPostedFile myFile = fileUploader.PostedFile;
int nFileLen = myFile.ContentLength;
if ((nFileLen > 0) &&
(System.IO.Path.GetExtension(myFile.FileName).ToLower() == ".jpg"))
{
// Read file into a data stream
byte[] myData = new Byte[nFileLen];
myFile.InputStream.Read(myData, 0, nFileLen);
myFile.InputStream.Dispose();
// Save the stream to disk as temporary file.
// make sure the path is unique!
System.IO.FileStream newFile
= new System.IO.FileStream
(Server.MapPath(filePath + "_temp.jpg"),
System.IO.FileMode.Create);
newFile.Write(myData, 0, myData.Length);
// run ALL the image optimisations you want here.....
// make sure your paths are unique
// you can use these booleans later
// if you need the results for your own labels or so.
// don't call the function after the file has been closed.
bool success = ResizeImageAndUpload(newFile, thumbPath, 100, 100);
success = ResizeImageAndUpload(newFile, filePath, 768, 1024);
// tidy up and delete the temp file.
newFile.Close();
// don't delete if you want to keep original files on server
// (in this example its for a real estate website
// the company might want the large originals
// for a printing module later.
System.IO.File.Delete(Server.MapPath(filePath + "_temp.jpg"));
}
}
}
}
Not sure if you need all these.... ? And I think my margins are all out.
Points of Interest
I think there is a way to complete this without saving a temp file then deleting it... but it was the easiest. It can also be expanded for GIF and PNG file types. But the application I need it for only uses JPG.
I have basically re-written this code from two other examples:
History
- 21st October, 2007: Initial post