天天看点

Javascrpt无刷新文件上传

最近工作中遇到上传文件问题,主要需求是一步点击上传,兼容ie8+,当时用的dojox/form/uploader控件,这两天扒了一下源码,明白了原理拿出来分享一下。

总体思路如下:

1、对于支持xmlhttprequest2的浏览器使用formdata通过ajax上传

2、对于ie10一下的浏览器使用iframe异步上传,还需后台服务器做相应处理,这部分也是dojo/request/iframe上传文件的原理。

一、使用formdata上传文件

如果直接向formdata的构造函数中传入表单元素,可以将表单元素的数据预先填入。

formdata的另一个便利之处就是不用明确指定content-type头部,xhr对象能够根据formdata实例自动配置适当的头部。下面是一个简单的上传文件demo。

server端代码使用formidable模块将文件暂存在tmp目录下。

 查看请求,xhr自动为我们设置请求头部。

Javascrpt无刷新文件上传

  兼容性问题

Javascrpt无刷新文件上传

二、使用iframe上传文件

  兼容旧版本的ie浏览器实现无刷新上传,只能借由iframe来实现,大多数类库的做法是动态插入一个iframe元素,将form元素的target属性设置为新添加的iframe,这样只刷新了iframe的内容而避免页面跳转到form元素的action属性所指定的url。这里我们根据dojo/request/iframe模块的原理来实现上传文件。

  该模块需要后台返回响应的格式来配合。将需要返回的信息放在`textarea`标签内。然后绑定iframe的load事件,通过`doc.getelementsbytagname('textarea')`取得textarea中的数据。

下面是简单的demo

Javascrpt无刷新文件上传
Javascrpt无刷新文件上传
Javascrpt无刷新文件上传

  不知大家有没有注意到,上面的demo是一步上传,选择好文件后直接上传到服务器,ie8以上的浏览器没问题,如果是在ie8中情况就有些棘手。ie中文件上传控件长成这个样子,单击一下button会弹出文件选择框,如果单击的是text部分,没有反映,你需要双击才会弹出选择框。一个办法是让鼠标尽量单击button部分,button的大小跟font-size有关。但如果你的可点击区域太大。。。。。

  所幸还是有解决办法的,这时需要在form中加一个label标签,for属性指向file。这样点击label时会触发for指向元素的click事件,这时label的自然行为。同时把file移除屏幕外。注意一定不能用input[type=button],在点击button时候调用file的click事件,然后在file change事件中调用form.submit方法,这种行为在ie中是被禁止的,回报“access denied”错误。

  

Javascrpt无刷新文件上传

参考资料

<a href="http://www.baidu.com/link?url=ds79hzgccxm9g9rqm2fbpa9unxd8wrsihf2ctk4ql6wnxbph2goegsyao5hnpgaudujsfxnqbxnl9zlgjsrtgk1q2a1pexyqbjch5-tgvps&amp;wd=javascript%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%20%e9%98%ae%e4%b8%80%e5%b3%b0&amp;issp=1&amp;f=8&amp;ie=utf-8&amp;tn=baiduhome_pg&amp;inputt=8293&amp;bs=ie8%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0" target="_blank">文件上传的渐进式增强 - 阮一峰的网络日志</a>

<a href="http://blog.teamtreehouse.com/uploading-files-ajax" target="_blank">uploading files with ajax</a>

<a href="http://stackoverflow.com/questions/9396411/ie-javascript-form-submit-with-file-input">ie javascript form submit with file input</a>

继续阅读