话说,还是有不少项目里提供让用户上传东西的。小到一个 wordpress 博客,大到一个文件存储网站。为了更好的用户体验。来学习两个新知识吧。HTML5 文件访问(File Access: FileReader)和拖放(Drag and Drop)。或许下个项目就能用上了。

一、起因

minus

今天看到 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。我们来看一下这种技术是怎么实现的吧。嗯,再回看上面的代码,还有我提了这么多次,其实,它就用到两个技术:

  1. FileReader,HTML5 File API
  2. Drag and Drop,似乎IE从 5.5 就支持了,都不敢说她是 HTML5 了

这里有两篇比较详细的文章,看(等看完我讲的,你再去看吧):

  1. Native HTML5 Drag and Drop
  2. Reading local files in JavaScript

现在 1:10 am 了,同学。明天还要上班。而具体讲来,还是需要很多时间滴。我们就简单一点。说些应该注意的吧。具体的实现,你看我 DEMO 的代码吧,和上面的文章吧。

一、 浏览器检测 & 支持

支持的浏览器并不多,我测试的是 Filefox 和 Chrome, winSafari 5.0.2 没通过。IE8 以下就更不用说了,当然,Opera 也没有支持。

if (window.FileReader) { 	// 做事的 } else { 	alert('你的浏览器不支持啊,同学') } 

从 Minus 的代码中可以看出,支持的有:

  1. Chrome 6+
  2. Firefox 3.6+
  3. Mac Safari 5.0+

其他的,就是浮云了。不过,这已经足够了,因为我们可以用 hack 来实现。我们这里,就讲可以用的吧。不可以的,就用原来项目中使用的方法吧。

二、注意事项

  1. 浏览器默认行为

    默认情况下,你向 Firefox 拖进一张图片,他可能会重定向于新页面。或者拖过一个链接,可能会让页面重定向。我想,你一定不会让你的用户一边上传,一边又打开一个本地文件页面,然后让他再跑回来上传的页面。那就,阻止浏览器默认行为是非常有必要的。

  2. 事件绑定

    你可能发现了,在 DEMO 当我们把东西拖进容器的时候,容器的边框样式变成虚线。因为我这里绑定了一个事件,当文件进入目标是,添加一个 dragenter 的 CLASSNAME。这里需要注意的事,减少事件的解法,你可以在事件 ondragenter 的时候,添加 CLASSNAME ,而 ondragleave 的时候,删除 CLASSNAME。但绑定在 dragover 上,他就像 mouseover ,在拖动的过程中不断解发,这对于浏览器的负担就很大了。可能会导致一些乱七八糟的,类似于崩溃之类的事。

  3. dataTransfer 的格式

    你可能需要用 e.dataTransfer.setData 和 e.dataTransfer.getData 来决定是否上传用户拖放的文件。

  4. File API 的状态和 result

    检测状态,以便下一步操作,而 result 则可以实现本地预览的功能,让用户知道自己要上传的东西是什么。

  5. File API 的读取格式
    • FileReader.readAsBinaryString(fileBlob) -  result 属性会包含一个文件的二进制的格式
    • FileReader.readAsText(fileBlob, opt_encoding) -  result属性将会包含一个文件的文本格式,默认解码参数是 “utf-8”。
    • FileReader.readAsDataURL(file) -  result 将会包含一个文件的 DataURL 格式(图片通常用这种方式)

四、具体的应用

其实我还没有见到国内用上这个技术的网站。刚才瞄了一下 QQ 微博。也没有。对于这些新技术。于我们前端开来,其实挑战并不是会不会使用,而是,如何去使用。

比如,在支付宝,下次需要改版用户上传身份证认证的时候,或许我会去推动这样的改进。又比如,如果是我在做 QQ 微博,或者任何一个微博,我将会提供一个让用户拖让一张图片就能上传的功能。

HTML5 能用到的地方太多了。就慢你没想法。因为别人其实并不清楚,连最清楚的你,前端,都不去推动,还能有谁去推动呢?

好吧。在接下来的项目中,你,或许也可以试试。