Total Pageviews

Tuesday 2 October 2012

用HTML5 拖放文件上传

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

一、Why

 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

SORRY 暂时没DEMO

三、How

好吧,确定是使用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
一、 Browse Support
支持的浏览器并不多,我测试的是 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 来实现。我们这里,就讲可以用的吧。不可以的,就用原来项目中使用的方法吧。
二、You Shoud Know
  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 格式(图片通常用这种方式)

4  Application

其实我还没有见到国内用上这个技术的网站。刚才瞄了一下 QQ 微博。也没有。对于这些新技术。于我们前端开来,其实挑战并不是会不会使用,而是,如何去使用。
比如,在支付宝,下次需要改版用户上传身份证认证的时候,或许我会去推动这样的改进。又比如,如果是我在做 QQ 微博,或者任何一个微博,我将会提供一个让用户拖让一张图片就能上传的功能。
HTML5 能用到的地方太多了。就慢你没想法。因为别人其实并不清楚,连最清楚的你,前端,都不去推动,还能有谁去推动呢?
好吧。在接下来的项目中,你,或许也可以试试.