摘要:在用戶執(zhí)行粘貼操作的時(shí)候,能夠獲得剪切板的內(nèi)容,本文討論一下這個(gè)問(wèn)題。目前只有支持獲取剪切板中的圖片數(shù)據(jù)。這么多的判斷條件,基本可以確定通過(guò)剪切板過(guò)來(lái)的是粘貼的文件。
在用戶執(zhí)行粘貼操作的時(shí)候,js能夠獲得剪切板的內(nèi)容,本文討論一下這個(gè)問(wèn)題。
目前只有Chrome支持獲取剪切板中的圖片數(shù)據(jù)。還好需要這個(gè)功能的產(chǎn)品目前只支持Chrome和Safari,一些Chrome的新特性是可以盡情使用了,還是能夠覆蓋到大部分用戶的。所以本文只討論Chrome如何使用和如何阻止Safari,原理大概了解了,再研究其他瀏覽器相關(guān)的問(wèn)題就容易多了。
paste事件可以用js給頁(yè)面中的元素綁定paste事件的方法,當(dāng)用戶鼠標(biāo)在該元素上或者該元素處于focus狀態(tài),綁定到paste事件的方法就運(yùn)行了。
綁定的元素不一定是input,普通的div也是可以綁定的,如果是給document綁定了,就相當(dāng)于全局了,任何時(shí)候的粘貼操作都會(huì)觸發(fā)。
事件對(duì)象 獲取事件對(duì)象先寫一下事件綁定的代碼
pasteEle.addEventListener("paste", function (e){ if ( !(e.clipboardData && e.clipboardData.items) ) { return; } });
粘貼事件提供了一個(gè)clipboardData的屬性,如果該屬性有items屬性,那么就可以查看items中是否有圖片類型的數(shù)據(jù)了。Chrome有該屬性,Safari沒(méi)有。
clipboardData介紹介紹一下clipboardData對(duì)象,它實(shí)際上是一個(gè)DataTransfer類型的對(duì)象,DataTransfer 是拖動(dòng)產(chǎn)生的一個(gè)對(duì)象,但實(shí)際上粘貼事件也是它。
clipboardData的屬性介紹
屬性 | 類型 | 說(shuō)明 |
---|---|---|
dropEffect | String | 默認(rèn)是 none |
effectAllowed | String | 默認(rèn)是 uninitialized |
files | FileList | 粘貼操作為空List |
items | DataTransferItemList | 剪切板中的各項(xiàng)數(shù)據(jù) |
types | Array | 剪切板中的數(shù)據(jù)類型 該屬性在Safari下比較混亂 |
items是一個(gè)DataTransferItemList對(duì)象,自然里面都是DataTransferItem類型的數(shù)據(jù)了。
屬性items的DataTransferItem有兩個(gè)屬性kind和type
屬性 | 說(shuō)明 |
---|---|
kind | 一般為string或者file |
type | 具體的數(shù)據(jù)類型,例如具體是哪種類型字符串或者哪種類型的文件,即MIME-Type |
方法 | 參數(shù) | 說(shuō)明 |
---|---|---|
getAsFile | 空 | 如果kind是file,可以用該方法獲取到文件 |
getAsString | 回調(diào)函數(shù) | 如果kind是string,可以用該方法獲取到字符串,字符串需要用回調(diào)函數(shù)得到,回調(diào)函數(shù)的第一個(gè)參數(shù)就是剪切板中的字符串 |
在原型上還有一些其他方法,不過(guò)在處理剪切板操作的時(shí)候一般用不到了。
types介紹一般types中常見(jiàn)的值有text/plain、text/html、Files。
值 | 說(shuō)明 |
---|---|
text/plain | 普通字符串 |
text/html | 帶有樣式的html |
Files | 文件(例如剪切板中的數(shù)據(jù)) |
pasteEle.addEventListener("paste", function (e){ if ( !(e.clipboardData && e.clipboardData.items) ) { return ; } for (var i = 0, len = e.clipboardData.items.length; i < len; i++) { var item = e.clipboardData.items[i]; if (item.kind === "string") { item.getAsString(function (str) { // str 是獲取到的字符串 }) } else if (item.kind === "file") { var pasteFile = item.getAsFile(); // pasteFile就是獲取到的文件 } } });
注意如果是string類型的數(shù)據(jù),可能針對(duì)具體是text/plain、text/html進(jìn)行分別的處理。
問(wèn)題來(lái)了一切看似都很順利,如果用戶粘貼了圖片,通過(guò)上面的方法我們是可以獲取到,可以對(duì)圖片進(jìn)行上傳等操作了。
首先要說(shuō)一下js通過(guò)剪切板能獲取到的圖片是怎么來(lái)的,它必須是用QQ截圖或者系統(tǒng)截圖功能截下來(lái)的圖片,或者是網(wǎng)頁(yè)上某個(gè)圖片單擊右鍵復(fù)制圖片等。
但是如果用戶復(fù)制Mac的Finder中的一個(gè)圖片文件,實(shí)際上js是沒(méi)有辦法獲取到這個(gè)圖片的。但是js確實(shí)會(huì)獲得一個(gè)圖片類型的文件,這個(gè)圖片實(shí)際上圖片在電腦中的圖標(biāo)標(biāo)識(shí),說(shuō)的比較抽象,直接上圖。
如果復(fù)制的是JPEG圖片,粘貼過(guò)來(lái)的卻是Mac上的文件縮略圖,后面依次是PNG、GIF、ZIP、DMG、Mac目錄的文件縮略圖。
很明顯,這不是我們期待得到的粘貼的結(jié)果,我們期待得到文件,但實(shí)際上卻得到該文件在操作系統(tǒng)上的縮略圖。
不過(guò)粘貼事件帶來(lái)的數(shù)據(jù)還有一個(gè)字符串,就是該文件的名字,所以可以用下面的方法Hack掉。
var cbd = e.clipboardData; if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files"){ return; }
這么多的判斷條件,基本可以確定通過(guò)剪切板過(guò)來(lái)的是粘貼的文件。我剛才測(cè)試了Windows的Chrome,不會(huì)有這個(gè)問(wèn)題,當(dāng)然也不能通過(guò)復(fù)制文件的方法得到任何文件。
問(wèn)題又來(lái)了當(dāng)我打算寫這篇博客的時(shí)候,Chrome開(kāi)發(fā)版已經(jīng)升級(jí)到了49,上面的Bug突然消失了,囧。
所以上面的Hack應(yīng)該加上版本限制了。
var ua = window.navigator.userAgent; ua.match(/Macintosh/i) && Number(ua.match(/Chrome/(d{2})/i)[1]) < 49
應(yīng)該在上面的Hack再加上這兩個(gè)判斷,即是Mac下的Chrome49版本以下就要return。
探究過(guò)程走的一點(diǎn)彎路由于公司IM系統(tǒng)正在遷移到V2消息系統(tǒng),而且現(xiàn)有的文件類庫(kù)沒(méi)有辦法滿足業(yè)務(wù)需求,要自己封裝一個(gè)文件上傳庫(kù)。
然后副總找到產(chǎn)品經(jīng)理,說(shuō)新版怎么不支持Excel的粘貼,臨時(shí)排期一天修復(fù)這個(gè)問(wèn)題,當(dāng)時(shí)是這樣解決的,如果items長(zhǎng)度是1并且是文件類型(單純粘貼一個(gè)文件),則上傳,如果items長(zhǎng)度是4且第4個(gè)是文件類型(經(jīng)過(guò)測(cè)試是Excel的粘貼結(jié)果),則上傳。
當(dāng)時(shí)擔(dān)心由于用戶各種誤操作,粘貼了不該粘貼的東西,文件上傳錯(cuò)誤,用了這種白名單機(jī)制去過(guò)濾,但是萬(wàn)一以后有比Excel粘貼得到的數(shù)據(jù)更其他的類型,就需要多帶帶寫代碼兼容,所以,現(xiàn)在改成了如果判斷是有Bug的情況,直接return,屬于黑名單機(jī)制,這樣以后再發(fā)現(xiàn)黑名單的情況,再添加。
可以拿來(lái)就用的代碼// demo 程序?qū)⒄迟N事件綁定到 document 上 document.addEventListener("paste", function (e) { var cbd = e.clipboardData; var ua = window.navigator.userAgent; // 如果是 Safari 直接 return if ( !(e.clipboardData && e.clipboardData.items) ) { return; } // Mac平臺(tái)下Chrome49版本以下 復(fù)制Finder中的文件的Bug Hack掉 if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" && ua.match(/Macintosh/i) && Number(ua.match(/Chrome/(d{2})/i)[1]) < 49){ return; } for(var i = 0; i < cbd.items.length; i++) { var item = cbd.items[i]; if(item.kind == "file"){ var blob = item.getAsFile(); if (blob.size === 0) { return; } // blob 就是從剪切板獲得的文件 可以進(jìn)行上傳或其他操作 } } }, false);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78477.html
摘要:屬性介紹默認(rèn)是默認(rèn)是在粘貼操作時(shí)為空剪切板中的各項(xiàng)數(shù)據(jù)剪切板中的數(shù)據(jù)類型。避免重復(fù)創(chuàng)建上傳中文件成功失敗處理已上傳上傳出錯(cuò)添加文件到隊(duì)列并上傳開(kāi)始上傳其他參考獲取剪切板內(nèi)容,控制圖片粘貼在線代碼編輯器事件說(shuō)明 Markdown編輯器選用https://simplemde.com它是一款純js實(shí)現(xiàn)的markdown編輯器。缺點(diǎn)不支持圖片上傳。那我們就得改造它。simplemde是基于co...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過(guò)一定長(zhǎng)度的文字就添加版權(quán)信息作者鏈接來(lái)源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁(yè)上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過(guò)一定長(zhǎng)度的文字就添加版權(quán)信息作者鏈接來(lái)源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁(yè)上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過(guò)一定長(zhǎng)度的文字就添加版權(quán)信息作者鏈接來(lái)源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁(yè)上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
閱讀 3631·2021-11-23 09:51
閱讀 2838·2021-11-23 09:51
閱讀 707·2021-10-11 10:59
閱讀 1711·2021-09-08 10:43
閱讀 3266·2021-09-08 09:36
閱讀 3326·2021-09-03 10:30
閱讀 3323·2021-08-21 14:08
閱讀 2240·2021-08-05 09:59