話說,還是有不少項(xiàng)目里提供讓用戶上傳東西的。小到一個(gè) wordpress 博客,大到一個(gè)文件存儲(chǔ)網(wǎng)站。為了更好的用戶體驗(yàn)。來學(xué)習(xí)兩個(gè)新知識(shí)吧。HTML5 文件訪問(File Access: FileReader)和拖放(Drag and Drop)。或許下個(gè)項(xiàng)目就能用上了。

一、起因

minus

今天看到 twitter 上有人在分享 Min.us 這個(gè)網(wǎng)站。說是只要把圖片進(jìn)去,就可以分享。是的,它確實(shí)是這樣。體驗(yàn)了一翻,無論從界面,還操作的方便性上說,這體驗(yàn)還真是很贊的。

不過,我更在意的是,他用了什么樣的技術(shù)。想著今晚回來瞄下代碼。這下,汗的事來了。這頁面看起來不像前端寫的啊。亂七八糟的。真是看不下去了。不過,為了更好的用戶體驗(yàn),看吧。從頁面的 HTML5 標(biāo)簽猜測(cè)到可能用到 HTML5 的某些 API,再查一下 JS 發(fā)現(xiàn)了這兩行:

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

先來個(gè)預(yù)覽吧,你可以先玩玩,再接著往下面看:HTML5 文件拖放上傳

三、如何實(shí)現(xiàn)

好吧,確定是使用HTML5。我們來看一下這種技術(shù)是怎么實(shí)現(xiàn)的吧。嗯,再回看上面的代碼,還有我提了這么多次,其實(shí),它就用到兩個(gè)技術(shù):

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

這里有兩篇比較詳細(xì)的文章,看(等看完我講的,你再去看吧):

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

現(xiàn)在 1:10 am 了,同學(xué)。明天還要上班。而具體講來,還是需要很多時(shí)間滴。我們就簡(jiǎn)單一點(diǎn)。說些應(yīng)該注意的吧。具體的實(shí)現(xiàn),你看我 DEMO 的代碼吧,和上面的文章吧。

一、 瀏覽器檢測(cè) & 支持

支持的瀏覽器并不多,我測(cè)試的是 Filefox 和 Chrome, winSafari 5.0.2 沒通過。IE8 以下就更不用說了,當(dāng)然,Opera 也沒有支持。

if (window.FileReader) { 	// 做事的 } else { 	alert('你的瀏覽器不支持啊,同學(xué)') } 

從 Minus 的代碼中可以看出,支持的有:

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

其他的,就是浮云了。不過,這已經(jīng)足夠了,因?yàn)槲覀兛梢杂?hack 來實(shí)現(xiàn)。我們這里,就講可以用的吧。不可以的,就用原來項(xiàng)目中使用的方法吧。

二、注意事項(xiàng)

  1. 瀏覽器默認(rèn)行為

    默認(rèn)情況下,你向 Firefox 拖進(jìn)一張圖片,他可能會(huì)重定向于新頁面。或者拖過一個(gè)鏈接,可能會(huì)讓頁面重定向。我想,你一定不會(huì)讓你的用戶一邊上傳,一邊又打開一個(gè)本地文件頁面,然后讓他再跑回來上傳的頁面。那就,阻止瀏覽器默認(rèn)行為是非常有必要的。

  2. 事件綁定

    你可能發(fā)現(xiàn)了,在 DEMO 當(dāng)我們把東西拖進(jìn)容器的時(shí)候,容器的邊框樣式變成虛線。因?yàn)槲疫@里綁定了一個(gè)事件,當(dāng)文件進(jìn)入目標(biāo)是,添加一個(gè) dragenter 的 CLASSNAME。這里需要注意的事,減少事件的解法,你可以在事件 ondragenter 的時(shí)候,添加 CLASSNAME ,而 ondragleave 的時(shí)候,刪除 CLASSNAME。但綁定在 dragover 上,他就像 mouseover ,在拖動(dòng)的過程中不斷解發(fā),這對(duì)于瀏覽器的負(fù)擔(dān)就很大了。可能會(huì)導(dǎo)致一些亂七八糟的,類似于崩潰之類的事。

  3. dataTransfer 的格式

    你可能需要用 e.dataTransfer.setData 和 e.dataTransfer.getData 來決定是否上傳用戶拖放的文件。

  4. File API 的狀態(tài)和 result

    檢測(cè)狀態(tài),以便下一步操作,而 result 則可以實(shí)現(xiàn)本地預(yù)覽的功能,讓用戶知道自己要上傳的東西是什么。

  5. File API 的讀取格式
    • FileReader.readAsBinaryString(fileBlob) -  result 屬性會(huì)包含一個(gè)文件的二進(jìn)制的格式
    • FileReader.readAsText(fileBlob, opt_encoding) -  result屬性將會(huì)包含一個(gè)文件的文本格式,默認(rèn)解碼參數(shù)是 “utf-8”。
    • FileReader.readAsDataURL(file) -  result 將會(huì)包含一個(gè)文件的 DataURL 格式(圖片通常用這種方式)

四、具體的應(yīng)用

其實(shí)我還沒有見到國(guó)內(nèi)用上這個(gè)技術(shù)的網(wǎng)站。剛才瞄了一下 QQ 微博。也沒有。對(duì)于這些新技術(shù)。于我們前端開來,其實(shí)挑戰(zhàn)并不是會(huì)不會(huì)使用,而是,如何去使用。

比如,在支付寶,下次需要改版用戶上傳身份證認(rèn)證的時(shí)候,或許我會(huì)去推動(dòng)這樣的改進(jìn)。又比如,如果是我在做 QQ 微博,或者任何一個(gè)微博,我將會(huì)提供一個(gè)讓用戶拖讓一張圖片就能上傳的功能。

HTML5 能用到的地方太多了。就慢你沒想法。因?yàn)閯e人其實(shí)并不清楚,連最清楚的你,前端,都不去推動(dòng),還能有誰去推動(dòng)呢?

好吧。在接下來的項(xiàng)目中,你,或許也可以試試。