ASP.NET中的缩略图应用

简介:

在开发Web应用程序时,常常都会遇到图片上传和浏览的问题,有两种方案可以用来解决这个问题:

    1. 将图片直接上传到服务器的硬盘上。优点是代码执行起来比较方便,给ASP.NET的执行进程赋予一定的权限,直接将操作的客户端文件保存到远程服务器上即可,并且在页面上读取图片非常方便,还可以直接设置图片的显示样式,如图片的大小、边框、链接地址等;缺点是安全性较差,从客户端访问服务器的目录存在一定的安全隐患,另外就是图片不便于管理,如用户删除图片、修改图片、图片上传后的文件名管理等,尤其是共享图片的管理。

    2. 将图片转存到数据库中。优点是图片便于管理,DBA可以统一对图片进行操作,用户也可以非常方便地修改和删除已有的图片;缺点是代码执行起来稍微麻烦,而且针对不同的数据库还需要编写不同的执行代码,另外就是在处理页面中一组连续的图片时会有些麻烦,可能需要通过多次访问数据库来获取到页面上的所有图片,以及读取图片时同时设置图片的显示样式、对上传图片的文件大小限制等。

    总之,两种解决方案各有利弊,但终究要选用哪种解决方案往往也是由项目需求所决定的,作为程序员本身,当然是希望越简单越好。其实个人觉得如果项目对图片的要求不是很高,而且数据量不太大,采用第一种方案比较合适,毕竟操作简单,实现起来比较容易,如果要对图片进行修改和删除的话,也可以增加一些补救措施。如用户上传图片的同时将图片的相关信息保存到数据库中,但图片文件本身保存到服务器的硬盘上,可以编写一个文件名生成程序用于在服务器上创建唯一的文件名,这样就可以避免当用户上传的图片与服务器上已有的图片文件名相同时文件被覆盖掉,数据库中保存文件的一个映射表用于进行图片的检索,当图片被修改或删除时根据映射表对磁盘上的文件进行相应的操作,操作成功后同时更新映射表。

    第一种方案在上传和读取图片时都很容易,相关的代码我就不再具体给出来了,这里具体看一下第二种方案的实现。

    首先是图片的上传。在ASP.NET中,我们在页面上可以直接使用Visual Studio提供的FileUpload控件,也可以使用input的file类型的标签,其中这两种控件在本质上并没有区别,只是微软提供的控件封装了一些属性和方法便于调用罢了(我个人推荐直接在页面上使用input type='file'的标签)。《由Stream.Position问题而引发的思考》一文中介绍了如何上传图片,在服务端得到要上传的图片后,可以通过调用SQL的存储过程将图片保存进数据库中。

    读取图片时可以根据关键字调用数据库的存储过程得到图片实体,然后操作该实体将图片的二进制数据Write到页面上。一个图片的实体类可以仅有与图片相关的属性,类似于下面这样:

复制代码
public   class  ImageEntity
{
    
public  ImageEntity()
    {
    }

    
public  ImageEntity( int  id,  string  title, Byte[] imageBlob,  string  type)
    {
        ID 
=  id;
        Title 
=  title;
        ImageBlob 
=  imageBlob;
        Type 
=  type;
    }

    
public   int  ID {  get set ; }
    
public   string  Title {  get set ; }
    
public   string  Type {  get set ; }
    
public  Byte[] ImageBlob {  get set ; }
}
复制代码

    问题的关键是得到图片的实体后怎样将图片Write到页面上指定的地方,并设置图片的大小呢?

    将图片Write到页面上可以通过MemoryStream的WriteTo方法,大致是这样的:

复制代码
Byte[] imageBlob  =  imageEntity.ImageBlob;
if  (imageBlob.Length  >   0 )
{
    
using  (MemoryStream stream  =   new  MemoryStream(imageBlob))
    {
        Response.ContentType 
=  imageEntity.Type;
        stream.WriteTo(Response.OutputStream);
        stream.Close();
    }
}
复制代码

     代码比较简单,没有什么很特别的地方,与在页面上输出其它内容的方式基本相同。不过这种方法只能将图片的内容输出到页面上,而不能在页面上指定的地方进行输出。要做到这一点,我们只能将输出图片的代码写在单独的一个页面中,然后在要显示图片的页面的指定位置写上<img>标签,并将它的src指向这个用来输出图片的页面的地址。这个方法很奏效!但仍然面临着一些问题,如设置图片显示时的大小。也许你会说直接设置<img>标签的Width和Height属性不就可以了吗?跟在第一种方案里面一样!事实上这种方法的效果并不是很好,第一种方案在实际应用中也会碰到类似的问题,如果我们仅仅只是设置了图片的高和宽,那么图片在显示时可能会变形甚至失真。解决这个问题的办法是采用.NET提供的图片缩略图功能,即采用Image对象的GetThumbnailImage方法。下面给出了一个完整的解决方案。

ThumbnailPage

    其中缺省使用了BLL命名空间下的imageBll.GetImageById方法,这个方法需要自己编写,主要功能就是根据传入的图片ID从数据库中读取图片,并返回一个图片的实体对象。页面接收四个参数,包括图片压缩的高和宽、是否以缩略图方式显示图片(如果为否则不用指定高和宽),图片ID。代码的核心部分为GetThumbNail方法,读者可以参考msdn中给出的例子http://msdn.microsoft.com/zh-cn/library/bb882583.aspx 。EncoderParameter构造函数中的第二个参数(例子中的50L)为指定图片的压缩级别,最高为100,数值越高表示压缩得越少,越接近原图片质量。按照指定高和宽压缩后的图片会根据你所指定的压缩级别丢失一部分像素(图片原尺寸大于压缩后的尺寸),或者补充像素(图片原尺寸小于压缩后的尺寸)。

    这里有一个小小的缺陷,因为图片是从数据库中读取的,如果页面上需要连续显示一组图片,并且要显示的图片数量比较多的话,采用此方法输出图片的时候就需要多次调用输出图片的页面,同时也就需要多次访问数据库,效率可能会有所降低,适当地采用数据库缓存可以来解决这个问题。还有就是当gif格式的图片存在多帧的动画时,被压缩后的图片只会显示第一帧。

    另外,有一些问题需要引起注意,在使用MemoryStream.WriteTo方法往页面上输出图片时可能会有异常抛出,使用前必须确保MemoryStream的实例在使用完后被显示关闭并释放(如使用Using语句),并且保存图片原始数据的MemoryStream与压缩后保存图片数据的MemorySream对象不是同一个对象。通过GetImageType方法得到正确的ImageFormat,有的时候图片的ContentType会有一些细微的区别,各种不同的ContentType是否代表了同一种ImageFormat需要认真确认,这些因素都可能导致图片显示时导致异常。异常可能并不会直接在页面上反映出来,在调用的地方,要显示的图片在发生异常时会显示一个红色的小叉,表示图片显示失败。


本文转自Jaxu博客园博客,原文链接:http://www.cnblogs.com/jaxu/archive/2009/06/12/1502269.html,如需转载请自行联系原作者


相关文章
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
683 11
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
271 0
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
11月前
|
C# Android开发 iOS开发
2025年全面的.NET跨平台应用框架推荐
2025年全面的.NET跨平台应用框架推荐
518 23
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
252 5
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
489 2
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
712 6
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
1480 3
|
缓存 Java API
【揭秘】.NET高手不愿透露的秘密:如何让应用瞬间提速?
【8月更文挑战第28天】本文通过对比的方式,介绍了针对 .NET 应用性能瓶颈的优化方法。以一个存在响应延迟和并发处理不足的 Web API 项目为例,从性能分析入手,探讨了使用结构体减少内存分配、异步编程提高吞吐量、EF Core 惰性加载减少数据库访问以及垃圾回收机制优化等多个方面,帮助开发者全面提升 .NET 应用的性能和稳定性。通过具体示例,展示了如何在不同场景下选择最佳实践,以实现更高效的应用体验。
259 3
|
前端开发 JavaScript 开发工具
跨域联姻:React.NET——.NET应用与React的完美融合,解锁前后端高效协作新姿势。
【8月更文挑战第28天】探索React.NET,这是将热门前端框架React与强大的.NET后端无缝集成的创新方案。React以其组件化和虚拟DOM技术著称,能构建高性能、可维护的用户界面;.NET则擅长企业级应用开发。React.NET作为桥梁,使.NET应用轻松采用React构建前端,并优化开发流程与性能。通过直接托管React组件,.NET应用简化了部署流程,同时支持服务器端渲染(SSR),提升首屏加载速度与SEO优化。
524 1
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
398 1