图像文件上传与存储的Web应用实现

在本文中,将探讨如何构建一个Web应用程序,允许用户上传和存储图像文件(如.jpg、.png、.gif等)以及相应的文本描述。这是一项之前从未尝试过的任务,因此通过Google搜索“在数据库文件系统中存储图像文件”来寻找解决方案。搜索结果显示了多种技术和观点,支持和反对将图像数据存储在数据库或文件系统中。然而,本文《在数据库还是文件系统中存储大对象:BLOB》总结了一个观点:“小于256K的对象最好存储在数据库中,而大于1M的对象最好存储在文件系统中。” 同样,关于即时调整图像大小的搜索也返回了各种编程技术。这里展示的代码是这些研究的结果。

本文不会讨论图像文件存储和调整大小的优缺点。将从将图像存储在文件系统中开始,同时将与图像相关的元数据存储在SQL Server数据库中。稍后,将撰写另一篇文章,描述将图像存储在数据库中的方法。

使用代码:

该Web项目使用了.NET 4.51框架,因此请确保系统上已安装。下载并解压缩Visual Studio解决方案到选择的文件夹,并使用Visual Studio 2012或更高版本打开它。

默认的aspx页面使用了标准的FileUpload、TextBox、Button和GridView控件。GridView列已转换为模板,GridView绑定到SqlDataSource控件。SqlDataSource控件又绑定到App_Data文件夹中找到的localDB。它包含一个表,用于存储文件名、文件路径和图像的文本描述。为简单起见,此应用程序仅接受MIME类型为"image/jpeg"的图形文件。其他类型,如PNG和GIF,可以通过在代码中进行少量更改来处理。该项目是使用Internet Explorer 11开发和测试的。

在Internet Explorer中运行代码并选择一个JPG图像上传。点击“提交照片”按钮开始处理。FileUpload控件在随后的回传中接收文件。按钮的点击事件处理程序检查文件的存在。如果不存在,或者不是JPEG MIME类型,则不处理数据。否则,控制权传递给ResizeAndSaveImage方法。

C# using System; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.IO; namespace StoringImages { public partial class Default : System.Web.UI.Page { protected void Button1_Click( object sender, EventArgs e) { if (FileUpload1.HasFile == false || FileUpload1.PostedFile.ContentType.ToLower() != " image/jpeg" ) { return ; } ResizeAndSaveImage(); SqlDataSource1.InsertParameters[ " FilePath" ].DefaultValue = Server.MapPath( " SavedImages" ); SqlDataSource1.InsertParameters[ " FileName" ].DefaultValue = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName); SqlDataSource1.InsertParameters[ " Description" ].DefaultValue = TextBox1.Text; SqlDataSource1.Insert(); } The first thing that must be done is to get the uploaded image into a Bitmap object and extract vital information: C# // Assumes JPG/JPEG images only protected void ResizeAndSaveImage() { using (Bitmap uploadedBmp = new Bitmap(FileUpload1.FileContent)) { decimal origHeight = uploadedBmp.Height; decimal origWidth = uploadedBmp.Width; int newHeight = 500 ; int newWidth = Convert.ToInt32(newHeight / (origHeight / origWidth));

在这里,原始图像的高度和宽度被保存,新调整大小的图像的高度被确定。在这种情况下,新的高度将是500像素。它可以是任何值,甚至比原始的还要大。新宽度的计算方式是,调整大小后的图像不会出现挤压或拉伸。接下来,创建一个Graphics对象。这个对象将处理图像数据。设置了几个渲染属性,以产生高质量的图像:

C# using (Graphics resizedGr = Graphics.FromImage(uploadedBmp)) { // Optional. These properties are set for the best possible quality resizedGr.CompositingMode = CompositingMode.SourceCopy; resizedGr.CompositingQuality = CompositingQuality.HighQuality; resizedGr.InterpolationMode = InterpolationMode.HighQualityBicubic; resizedGr.SmoothingMode = SmoothingMode.HighQuality; resizedGr.PixelOffsetMode = PixelOffsetMode.HighQuality;

此时,使用新的、更小的高度和宽度属性实例化一个新的Bitmap:

C# using (Bitmap resizedBmp = new Bitmap(uploadedBmp, newWidth, newHeight)) { The Graphics object is commanded to draw the new image into the new smaller Bitmap. A MemoryStream object is created and the new Bitmap then saves the file to memory with the proper MIME type encoding. The memory file is converted to a byte array that is in turn saved to disk: C# resizedGr.DrawImage(resizedBmp, 0 , 0 ); using (MemoryStream resizedMs = new MemoryStream()) { System.Drawing.Imaging.EncoderParameters encParms = new System.Drawing.Imaging.EncoderParameters( 1 ); // This allows jpeg compression to be set to 90 encParms.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ( long ) 90); resizedBmp.Save(resizedMs, GetImgCodecInf( " image/jpeg" ), encParms); long msLen = resizedMs.Length; byte[] resizedData = new byte[msLen]; resizedData = resizedMs.ToArray(); using (System.IO.FileStream fStream = new System.IO.FileStream(Server.MapPath( " SavedImages" ) + @" \" + Path.GetFileName(FileUpload1.PostedFile.FileName), System.IO.FileMode.Create)) { fStream.Write(resizedData, 0 , resizedData.Length); } The image now has been resized and stored on disk. The next step is to create yet another smaller corresponding thumbnail image that can be used as a preview in the GridView control. This step is essentially the same as the first image processing routine accept the height of the finished image is 100 pixels. Also the image quality parameters have been left out and to appease those who prefer not to use the C# using statement, the FileStream and Graphics object are closed and disposed of programmatically: C# // Repeat process to create a thumbnail image, reusing resizedBmp // This approach does not use the 'using' statement or the // high quality graphics properties origHeight = resizedBmp.Height; origWidth = resizedBmp.Width; int thumbHeight = 100 ; int thumbWidth = Convert.ToInt32(thumbHeight / (origHeight / origWidth)); Bitmap thumbBmp = new Bitmap(resizedBmp, thumbWidth, thumbHeight); Graphics thumbGr = Graphics.FromImage(thumbBmp); thumbGr.DrawImage(thumbBmp, 0 , 0 ); MemoryStream thumbMs = new MemoryStream(); thumbBmp.Save(thumbMs, System.Drawing.Imaging.ImageFormat.Jpeg); long thumbmsLen = thumbMs.Length; byte[] thumbData = new byte[thumbmsLen]; thumbData = thumbMs.ToArray(); System.IO.FileStream tStream = new System.IO.FileStream(Server.MapPath( " SavedImages" ) + @" \thmb_" + Path.GetFileNameWithoutExtension(FileUpload1.PostedFile.FileName) + Path.GetExtension(FileUpload1.PostedFile.FileName), System.IO.FileMode.Create); tStream.Write(thumbData, 0 , thumbData.Length); tStream.Close(); thumbGr.Dispose(); thumbBmp.Dispose(); thumbMs.Dispose(); } } } } // Returns an object with all codec data protected ImageCodecInfo GetImgCodecInf( string mimeType) { ImageCodecInfo[] imgCodecInfo = ImageCodecInfo.GetImageEncoders(); foreach (ImageCodecInfo infoItem in imgCodecInfo) { if (infoItem.MimeType.ToString().ToLower() == mimeType.ToLower()) { return infoItem; } } return null ; } }

最后,控制权返回到按钮点击事件处理程序,SqlDataSource插入参数被更新,表中插入了新记录。由于所有操作都发生在回传期间,GridView会自动用新记录更新。

结论:

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485