Web-Secret图片服务六优化您的用户体验
Web Secret:图片服务(六)——优化您的用户体验
阅读:
l
[Web Secret
:图片服务(一)——构建一个基本的图片服务]( )
l
[Web Secret
:图片服务(二)——扩展您的图片服务]( )
l
[Web Secret
:图片服务(三)——为您的服务加上缓存]( )
l
[Web Secret
:图片服务(四)——重新设计您的存储架构]( )
l
[Web Secret
:
图片服务(五) ——
提高服务的性能]( )
我们在第一篇就提到了最基本的图片服务需要一个图片上传页面,下面是最简单的
HTML
代码:
<
form
id
=“from1”
action
=“UploadImage.php”
enctype
=“multipart/form-data”>
<
label
for
=“imageTitle”>
标题 : </
label
<
input
type
=“text”
name
=“Title”
id
=“imageTitle”
/><
br
/>
<
label
for
=“imageFile”>
图片 : </
label
<
input
type
=“text”
name
=“ImageFile”
id
=“imageFile”
value
="
请选择文件 "
/><
br
/>
<
input
type
=“submit”
value
="
上传 "
/>
</
form
除了需要在表单增加“
enctype
=“multipart/form-data”
”之外,其它也不用太多的调整。那我们需要怎样的功能呢,才能够使我们精心设计的服务用户体验更好:
l
我希望支持一次性上传多个文件
l
我希望上传过程中可以显示进度
l
我希望限制上传文件的格式,比如只支持
jpg(jpeg)
、
png
和
gif
格式的图片
l
因为和其它业务集成(如发
blog
或者帖子),我希望不刷新当前页面
l
……
关于文件上传有相当多成熟的解决方案,而且相当多的方案是和服务器代码集成的,你可以根据自己的需要,大多是基于
JavaScript
解决方案的,你可以通过搜索“
”找到很多脚本类库,如果您是使用
,那么可以通过
找到更多的解决方案,如果是使用
,也有很多的插件可以选择,你可以在
找到很多有用的插件,当然了,还有
、
、
、
等框架可以选择,而针对不同的框架,也提供了对于文件上传的支持。我没有给出具体的链接,只是想解释一下不同需求的技术考虑:
1、 上传多个文件
最简单的做法是在上传表单内放置多个
的
HTML
元素。另外一种方式就是用脚本动态生成文件上传控件,如
所展示的。
2、 限制上传的文件格式
在
form
的
onsubmit
事件中判断文件后缀,如果不符合期望的文件格式,取消表单提交。
3、 不刷新当前页面
我们可以选择用
Iframe
,在
IFrame
内的页面只显示上传相关的页面,比如
CSDN
的发表
blog
页面,然后通过脚本的方式将上传之后的图片地址通知上级页面。
4、 显示文件上传进度
对于上传大文件和批量上传的时候尤其有用,因为文件上传过程中是阻塞的,因为文件大或者网络的缘故,将可能导致阻塞时间过长,另外默认情况下上传的所有数据都在服务器内存缓存,如果上传过大的文件,将有可能导致拒绝服务攻击(
DOS
)。
对于
ASP.NET
,默认情况文件大小的上限是
4MB
,这是在系统的
machine.config
中定义的,当然了,你可以在
web.config
中覆盖,具体如下:
*将默认的大小限制修改为
20480KB* *,也就是
20M* *,超时实践为
240* 秒
<system.web>
</system.web>
这种调整是针对于整个网站而言的,如果不想如此做,可以针对某一个目录进行调整,如
/Upload/ImageUpload.aspx
,只要调整
Upload
目录就可以。
<system.web>
</system.web>
但是对于更大的文件呢,这里完成的仅仅是一步,一篇名为
的文章揭示了更多有关与
IIS
配合完成文件上传的细节。从技术上讲是
利用隐含的
HttpWorkerRequest
,用它的
GetPreloadedEntityBody
和
ReadEntityBody
方法从
IIS
为
ASP.NET
建立的
pipe
里分块读取数据,对于每块分块进行分析并存储为临时文件,然后给浏览器一个回调地址,那么浏览器就能够显示当前完成的进度了。这时候需要使用到
HttpModule
,这个时候将会导致原来的文件上传无法获得文件流的情况,当然了,也不是没法解决。目前有几个方案可以选择:
·
(
MediaChase
公司,
$310
以上)
·
(
Telerik
公司,
$249
)
·
(免费,遵守
LGPL
协议)
·
(免费)
在
PHP
的环境下同样有很多种方案可以选择,我只是列举出几个主要的:
1.
PHP
的创始人
Rasmus Lerdorf
写的
APC
扩展模块来实现,
。
实现方法:
l
安装
APC
,参照官方文档安装,可以使用
PECL
模块安装方法快速简捷
l
配置
php.ini
,设置参数
apc.rfc1867=1
,使
APC
支持上传进度条功能,在
APC
源码说明文档里面有说明
代码范例:
if
(
$_SERVER
[
‘REQUEST_METHOD‘
] ==
‘POST‘
)
{
//
上传请求
$status
=
apc_fetch
(
‘upload_‘
.
$_POST
[
‘APC_UPLOAD_PROGRESS‘
]);
$status
[
‘done‘
] =
1
;
echo
json_encode
(
$status
);
//
输出给用户端页面里的 ajax 调用,相关文档请自己寻找
exit;
}
elseif
(isset(
$_GET
[
‘progress_key‘
]))
{
//
读取上传进度
$status
=
apc_fetch
(
‘upload_‘
.
$_GET
[
‘progress_key‘
]);
echo
json_encode
(
$status
);
exit;
}
else
{
//
其他代码,比如上传表单等
}
2.
使用
PECL
扩展模块
uploadprogress
实现(
)
3.
UGiA
,可以通过
查阅详细的文档
我们上述谈到的都是标准基于
Ajax
和服务器端实现的,为了让客户端显示更加流畅,我们还有其他技术可以选择:
ü
ActiveX
通过
ActiveX
可以实现你需要的任何功能,比如上传前压缩,转换,也能够上传多图片,对于专业的图片
/
相册网站,提供一个这样的桌面工具也许是不错的选择,微软的
space
相册也提供了
[Windows Live
上载工具]( )
,
也提供了自己的上传工具。如果您的网站也想用这样的
ActiveX
而又没有能力自己开发的话,可以考虑购买
提供的
,它的强大功能应该能够满足您的业务需求。
限制
ActiveX
控件使用的一个关键因素是需要用户安装,同时涉及到安全的原因,不是特定用途的情况下,一般不会推荐这样的方案。
ü
Flash
从
Flash 8
开始,提供了
FileReferenceList API
,正是因为如此,你可以利用它来实现多文件上传,同时得到详细的文件上传进度。如果你熟悉
ActionScript
,那么可以利用
Flex
或者
Flash
来编写自己的文件上传组件。利用
flash
的另外一个优势就是可以和
javascript
无缝集成,
《
[Ajax+Flash
实现多文件上传]( )
》展示了不同的解决方案。
CodeProject
站点上也提供了
,
鉴于目前
flash
播放器的市场占有率,如果不是出于特殊的原因,您几乎可以不用考虑没有安装
flash
和不支持
javascript
的情况(试想一下,不支持
javascript
,也就别谈
ajax
,不支持
flash,
还有哪个
web 2.0
网站是可以玩的?),这时
flash
作为客户端文件上传的解决方案是不错的选择。
ü
作为号称
flash
杀手的
sliverlight
,目前已经发展到
3.0 Beta
,据微软的数据显示,全球已经
1/4
的浏览器安装了
Sliverlight
运行时,不过在国内的用户数还是值得怀疑的(可爱又该死的番茄花园),同样作为浏览器插件,也有越来越多关于文件上传的解决方案。
上你可以找到
,如果你能够确定你的目标用户已经安装或者允许安装
sliverlight
的话,也不妨考虑。
我们刚才讨论了关键文件上传相关的解决方案,不管是
Ajax
还是
ActiveX
、
Flash
还是
sliverlight
,都有不同的选择,如果你希望简单又美观的话,
flash+
服务器代码可能是一个不错的选择,比如
asp.net
,让你自己实现进度条或者编写
httpmodule
的话,并不是那么容易的,当然了,如果你有针对语言的完整解决方案,也可以如此使用。
最后我们来看一下图片的显示,作为典型的前端技术,不管是
javascript
还是
flash
或者
silverlight
,要列出清单的话,估计都会超过
1000
个,形形色色的插件、组件都可以帮我们来完成这个工作,至于该如何选择,我的原则是尽可能简单,不要为了特效而无畏地消耗浏览器的运算资源,如果访问您的网站会到导致用户
CPU
过高的话,这不是一件好事情。
如果你的业务比较简单,就选择一个适合自己的插件就可以了,如果比较复杂,需要圈人、
Tag
、留下脚印等等流行的
SNS
功能的话,更好的建议是自己开发,如果特效不是很多,用
ajax
会快一点,如果是特效比较多,虽然
Ajax
也能够完成许多效果的模拟,但是运行效率会存在问题,这时可以选择用
ActionScript
来开发
Flash
,你是设计师,你就选择
Flash
,如果是开发人员,需要大量的和后台数据交互,你选择
Flex
,熟悉
C#
的话,用
Silverlight
也可以。
全文到这里已经讨论了一个图片服务可能涉及的方方面面(至少我想到的)。我的初衷并不是一定要构建一个如此复杂的图片服务,这也是我分成多个篇幅的重要原因,在不同篇幅里关注和讨论的内容是不一样的。我只是希望通过这样的探讨来阐述作为一个架构师(或者在路上)你在面对业务的时候应该如何思考问题。
没有哪一个环节是必须的,但是任何一个问题都有可能是你碰到的,这个时候你对于解决方案的平衡尤为重要,有一些可以简化,有一些需要深入,也有一些可以放弃。而作为
Web
架构师,除了需要考量你技术的全面性,更加考虑你对于业务的理解力和掌控的尺度,只有这样,才能够在你的技术框架设计中找到平衡。
而平衡的能力,是平衡业务与技术实现的能力,也是一个优秀的架构师最基本的素质。
预告:
接下来我将探讨
Web 2.0
网站里头大规模用户的互动问题——
WebIM
,大多网站想提供却发现并不那么容易的事情。我们将会涉及到
Ajax
、
Comet
和服务器端的大规模用户连接的设计,敬请期待。