最近,在后台实现广告管理系统,有一个表单选项,想利用SWFUpload组件来实现。现在将该组件的认识和理解记录如下:方便有需要的同行查看.
一、首先来比较下目前的几种的客户端上传:
1、File表单
使用标准的HTML元素提供的File表单是最原始、传统的上传方式,他的优势在于浏览器的广泛兼容性,除了服务端需要处理Files信息以外,不需要额外的处理程序即可完成文件上传。
但使用File表单上传文件会造成页面的刷新,尤其是在上传大文件的时候,在文件上传过程中,用户需要傻等在一个空白页面前,没有任何反馈信息来提示用户当前的上传进度。同时无法在客户端对文件大小做检测。
2、IFrame结合File表单
使 用一个含有file表单的iframe来完成文件上传,能够避免文件上传过程中的页面刷新,在一定程度上改进了用户体验,但同样没有解决大文件上 传时候缺少反馈信息的问题。相比File表单上传,此方式还需要对程序做额外的处理,同时需要JS的支持,复杂度稍微增加了一些。
3、IFrame、File表单结合AJAX
在方式2的基础上引入AJAX来实时跟服务端脚本获取当前的上传进度,实现了页面无刷新、实时更新上传进度的功能。但程序的复杂度又增加了一个级别,由于要不断跟服务端发送请求,同时也增加了服务端的压力。
4、Activex控件
使用控件方式完成的上传在功能和效率上都很不错,页面无刷新、显示上传进度、批量上传,个人认为遗憾就在于需要在浏览器上安装控件,而且只能支持IE,弹出那么个安装提示可能会吓倒多数用户,开发的复杂度也提高了。
5、Flash
Flash的FileReference类提供了文件上传功能,相对于传统的File表单而言,Flash上传能够获取客户端的文件的更多信息反馈,例如文件大小、类型、创建、修改时间等,利用这些信息可以在客户端对文件进行类型和大小等属性的一次过滤。
FileReference类提供了多文件上传功能。
Flash直接向服务端发送文件数据,因此Flash本身是可以随时知道文件上传数据而显示上传进度,而不需要使用AJAX的方式不断跟服务端发送请求增加服务端的压力。
弊端在于客户端需要Flash播放器的支持,而且在一个页面中插入一个Flash,从UI元素的统一角度来看,似乎有些别扭,如果页面需要更改风格,那么Flash还需要重新修改然后编译,而且程序开发的复杂度也提高了。
6、Flash结合JavaScript
在方式5的基础上,将Flash隐藏起来,利用JavaScript来控制Flash元素处理文件上传,Flash使用 ExternalInterface来完成跟JavaScript的通信,将页面元素的控制权交给JS。这样就避免了方式5中的UI元素不统一、修改不灵 活的弊端。但代价就是Flash程序开发的复杂度再次提高了,同时也需要更高的JS和XHTML开发能力。
以 上列举了目前我所了解的浏览器环境下文件上传的方式,并对其优劣都做了简单的罗列,在实际开发中我们可以根据自己的应用来选择合适的方式,假如我 们的需求只是用户给自己上传一个10K不到的头像,如果我们还大费周折地实现了头像上传的进度提示,那就是事倍功半了,因为在目前的绝大多数网络情况下, 一个10K的文件传输是一眨眼的功夫。
二、关于SWFUpload
如果项目中在浏览器环 境下需要高级上传功能,那么我个人认为使用方式6是最合适的选择,而SWFUpload在很大程度上降低了开发的复杂度,它提 供了一个编译好的不包含任何UI元素的Flash影片,并将浏览器的中UI交给开发人员来控制。开发人员能够利用 XHTML,CSS,Javascript来定制符合他们网站风格的UI上传元素。然后使用它提供的一组简单的JS事件来更新上传状态,开发人员能够利用 这些事件来及时更新页面中的上传进度UI,针对错误、异常等给用户反馈。
关于SWFUpload的使用,我已经将官方文档结合自己使用的关键点做了一个翻译和备注,可见SWFUpload翻译,网上也经常有朋友问我要例子演示,实际上官方的demo就是很好的例子,自己下载下来仔细看看问题不大的。这里我只是想针对一些朋友问起过的问题的误区来回答下SWFUpload不能做什么。
1、它不能在服务端写文件
你 可以把SWFUpload理解成是一个功能更强大一点的file表单,它的能力范围仅仅在客户端作用,它只能往upload_url对应的服务端 程序发送文件数据,并不能自己自动在服务端写一个文件。因此upload_url对应的服务端程序需要跟接收传统的File表单信息一样接收Flash传 递过来的文件信息,然后根据自己需求完成该文件的存储。
2、它不能保留原有的Session进程
SWFUpload在上传时相当于重新开辟了一个新的Session进程,因此无法与原有程序的Session保持一致,这就造成了你无法像传统的表单上传那样访问客户端标识。
如果你需要这个客户端标识,那么就需要额外程序处理了。你可以在发送文件信息之前,利用JS将获取的Cookie信息写入到SWFUpload的配置中,如果你使用的是FLASH9版本,你还可以把这个信息写入到POST变量中一同发送。
或者在页面初始化SWFUpload实例的时候,可以直接将客户端标识写入在设置中(例如,在upload_url中增加客户端标识),无需随后使用JS来增加标识。
3、在选择文件的时候,它不会让超出文件大小限制的文件不可见
假如你设置的是允许用户上传3M以下的JPG图片,那么当用户打开文件选择对话框时,他只能看到系统中的文件夹和JPG图片,类型过滤是有效的,但大小过滤无效,也就是说你看到的文件并非都是3M以下的。
实际上文件大小的过滤是在文件入队的时候进行的,如果你选择的是一个5M的文件加入队列,那么会触发一个QueueError事件来提示你该文件没有通过过滤检测。
4、即使你用的是Flash9版本,它也不能自动把你的表单一起自动提交到服务端
AS3中新的URLRequest对象让文件上传的时候可以一同发送POST变量,但这一过程并不是自动的,因此当你上传文件的时候,SWFUpload还没有智能到自动识别你的Form中的所有表单元素,并把他们一起POST到服务端。
如果你确实有这个需求,那么在上传前,你可以使用JS将目标表单的name和value构造成值对,然后使用addPostParam或者addFileParam方法来设置POST变量跟文件一同提交到服务端。
如果不想采取这种方式,那么还有个省力的方式。你可以先上传文件,当该文件上传完成以后利用JS来提交Form表单,由服务端逻辑来完成这两次“异步”提交数据的关联性,该实现方式的过程跟IFrame结合File表单实现异步上传相同。
5、它不能自动完成多文件上传
SWFUpload 提供文件多选功能,但并没有提供多文件自动上传功能。多选的文件都会插入到上传的文件队列中,如果你要完成多文件上传,那么可以 在uploadComplete事件的回调中调用startUpload方法来启动下一个文件的上传。如此进行下去,直到整个文件队列中的文件全部自动上 传完成,整个上传才会停止。
6、它不能真正限制用户上传的文件数量
设置中的file_upload_limit只是针对当前页面中的一个SWFUpload实例有效,当页面刷新,该值就被恢复重置了。它并不能记住先前的上传数量。如果你需要严格限制用户上传的文件数量,那么就需要通过服务端逻辑来实现。
7、它不是“多线程”的,一个时间点只能上传一个文件
SWFUpload虽然能完成多文件上传,但它是“单线程”的,当此刻有文件上传的时候,无法启动下一个文件上传,必须等待当前文件上传结束(退出、停止、上传完毕)。