在实际开发中经常需要从客户端上传图片到服务器,但FileUpload并不能提供图片的预览功能,本文介绍如何开发一个支持图片预览功能的图片上传组件(注:图片上传预览功能也可以通过JavaScript客户端脚本实现,本文采用的方式是服务器预存储图片的预览方式)。
我们希望该控件具备如下功能:
- 具备两种UI视图,分别为预览视图和编辑视图,预览视图允许用户浏览刚才上传的图片文件,编辑视图允许用户重新上传一个文件和文件说明,或编辑已有图片的说明。通过功能按钮可以两种视图之间可以互相切换。如下图所示:
- 允许用户将上传的图片删除
设计控件外观
预览图片是两种视图公用的部分,因此在MultiView外放置一个Image用于图片预览,我们用MultiView控件来实现两种不同视图外观的切换,在两种视图状态中分别添加如下控件:
- 预览视图
ImageButton: 编辑按钮,点击该按钮时切换到编辑视图
ImageButton: 删除按钮,点击该按钮是删除该图片
- 上传视图
FileUpload: 上传图片选择框
TextBox: 上传图片描述
LinkButton: 保存按钮,点击该按钮上传图片并切换到预览视图
LinkButton: 取消按钮,点击该按钮直接切换到预览视图
视图之间的切换可以通过设置MultiView的ActiveViewIndex属性来进行配置。
控件属性
为控件提供如下公共属性,以便与外部调用方进行交互。
- ImageUrl:读/写 当前显示图片的路径,支持服务器路径符~
- ImageDescn: 读/写,获取图片说明,显示在图片的alt属性中
- ImageID:读写,获取或设置图片ID, 没有图片是为空
- HasFile: 只读,获取目前容器中是否有图片,当设定ImageUrl, ImageDescription, ImageID属性时该字段自动置为True
控件事件
- Saving: 用户点击保存按钮时发生,从事件参数中获取图片描述和图片流
- Canceling: 用户点击取消按钮时发生
- Deleting: 用户点击删除按钮时发生,通过ImageID获取当前图片ID
为了使用户在Saving事件中可以从事件参数中获取客户端文件流,我们创建了相应的委托和事件参数:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
通过这种方式,用户在Saving事件中,可以直接从事件参数中捕获到客户端的上传文件流HttpPostedFile。获取客户端上传的文件流有两种方式,第一种为直接从FileUpload的PostedFile属性中读取,或者可以从Request.Files中获取,本文采用了后一种方式。
加入AJAX特性
为了避免视图切换过程中的频繁返送,我们为控件加入AJAX特性,用UpdatePanel将MultiView包装起来,但是FileUpload控件只有在整个页面返送的时候才可以正常取得文件,解决这个问题,我们把保存按钮设置为UpdatePanel的Trigger,所有功能就可以工作正常了。
ASCX
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)