话说,还是有不少项目里提供让用户上传东西的。小到一个 wordpress 博客,大到一个文件存储网站。为了更好的用户体验。来学习两个新知识吧。HTML5 文件访问(File Access: FileReader)和拖放(Drag and Drop)。或许下个项目就能用上了。
一、起因
今天看到 twitter 上有人在分享 Min.us 这个网站。说是只要把图片进去,就可以分享。是的,它确实是这样。体验了一翻,无论从界面,还操作的方便性上说,这体验还真是很赞的。
不过,我更在意的是,他用了什么样的技术。想着今晚回来瞄下代码。这下,汗的事来了。这页面看起来不像前端写的啊。乱七八糟的。真是看不下去了。不过,为了更好的用户体验,看吧。从页面的 HTML5 标签猜测到可能用到 HTML5 的某些 API,再查一下 JS 发现了这两行:
function isValidBrowser() { var browser = BrowserDetect.browser; var version = BrowserDetect.version; var OS = BrowserDetect.OS; //alert(browser+','+version+','+OS); return ( (browser == 'Chrome' && version >= 6) || (browser == 'Firefox' && version >= 3.6) || (browser == 'Safari' && version >= 5.0 && OS == 'Mac') || ("FileReader" in self && "ondrag" in document) ); }
二、DEMO
先来个预览吧,你可以先玩玩,再接着往下面看:HTML5 文件拖放上传
三、如何实现
好吧,确定是使用HTML5。我们来看一下这种技术是怎么实现的吧。嗯,再回看上面的代码,还有我提了这么多次,其实,它就用到两个技术:
- FileReader,HTML5 File API
- Drag and Drop,似乎IE从 5.5 就支持了,都不敢说她是 HTML5 了
这里有两篇比较详细的文章,看(等看完我讲的,你再去看吧):
- Native HTML5 Drag and Drop
- Reading local files in JavaScript
现在 1:10 am 了,同学。明天还要上班。而具体讲来,还是需要很多时间滴。我们就简单一点。说些应该注意的吧。具体的实现,你看我 DEMO 的代码吧,和上面的文章吧。
一、 浏览器检测 & 支持
支持的浏览器并不多,我测试的是 Filefox 和 Chrome, winSafari 5.0.2 没通过。IE8 以下就更不用说了,当然,Opera 也没有支持。
if (window.FileReader) { // 做事的 } else { alert('你的浏览器不支持啊,同学') }
从 Minus 的代码中可以看出,支持的有:
- Chrome 6+
- Firefox 3.6+
Mac Safari 5.0+
其他的,就是浮云了。不过,这已经足够了,因为我们可以用 hack 来实现。我们这里,就讲可以用的吧。不可以的,就用原来项目中使用的方法吧。
二、注意事项
- 浏览器默认行为
默认情况下,你向 Firefox 拖进一张图片,他可能会重定向于新页面。或者拖过一个链接,可能会让页面重定向。我想,你一定不会让你的用户一边上传,一边又打开一个本地文件页面,然后让他再跑回来上传的页面。那就,阻止浏览器默认行为是非常有必要的。
- 事件绑定
你可能发现了,在 DEMO 当我们把东西拖进容器的时候,容器的边框样式变成虚线。因为我这里绑定了一个事件,当文件进入目标是,添加一个 dragenter 的 CLASSNAME。这里需要注意的事,减少事件的解法,你可以在事件 ondragenter 的时候,添加 CLASSNAME ,而 ondragleave 的时候,删除 CLASSNAME。但绑定在 dragover 上,他就像 mouseover ,在拖动的过程中不断解发,这对于浏览器的负担就很大了。可能会导致一些乱七八糟的,类似于崩溃之类的事。
- dataTransfer 的格式
你可能需要用 e.dataTransfer.setData 和 e.dataTransfer.getData 来决定是否上传用户拖放的文件。
- File API 的状态和 result
检测状态,以便下一步操作,而 result 则可以实现本地预览的功能,让用户知道自己要上传的东西是什么。
- File API 的读取格式
FileReader.readAsBinaryString(fileBlob)
- result
属性会包含一个文件的二进制的格式FileReader.readAsText(fileBlob, opt_encoding)
- result
属性将会包含一个文件的文本格式,默认解码参数是 “utf-8”。FileReader.readAsDataURL(file)
- result
将会包含一个文件的 DataURL 格式(图片通常用这种方式)
四、具体的应用
其实我还没有见到国内用上这个技术的网站。刚才瞄了一下 QQ 微博。也没有。对于这些新技术。于我们前端开来,其实挑战并不是会不会使用,而是,如何去使用。
比如,在支付宝,下次需要改版用户上传身份证认证的时候,或许我会去推动这样的改进。又比如,如果是我在做 QQ 微博,或者任何一个微博,我将会提供一个让用户拖让一张图片就能上传的功能。
HTML5 能用到的地方太多了。就慢你没想法。因为别人其实并不清楚,连最清楚的你,前端,都不去推动,还能有谁去推动呢?
好吧。在接下来的项目中,你,或许也可以试试。