欧美日韩国产一区二区|qovd片|小明个人发布看看|小浪货你夹真紧水又多|老头把我添高潮了A片故|99热久久精品国产一区二区|久久久春色AV

兼容chrome、firefox、ie11 js實(shí)現(xiàn)ctrl+v粘貼上傳圖片

我們或多或少都使用過(guò)各式各樣的富文本編輯器,其中有一個(gè)很方便功能,復(fù)制一張圖片然后粘貼進(jìn)文本框,這張圖片就被上傳了,那么這個(gè)方便的功能是如何實(shí)現(xiàn)的呢?
原理分析
提取操作:復(fù)制=粘貼=上傳
在這個(gè)操作過(guò)程中,我們需要做的就是:監(jiān)聽(tīng)粘貼事件=獲取剪貼板里的內(nèi)容=發(fā)請(qǐng)求上傳
為方便理解下文,需要先明白幾點(diǎn):
我們只能上傳網(wǎng)頁(yè)圖(在網(wǎng)頁(yè)上右鍵圖片,然后復(fù)制)和截圖(截圖工具截的圖片,eg:qq截圖),不能粘貼上傳系統(tǒng)里的圖片(從桌面上、硬盤里復(fù)制),他們是存在完全不同的地方的 。截圖工具截的圖與在網(wǎng)頁(yè)點(diǎn)擊右鍵復(fù)制的圖是有些不同的 , 因此處理方式也不一樣 。知悉paste event這個(gè)事件:當(dāng)進(jìn)行粘貼(右鍵paste/ctrl v)操作時(shí),該動(dòng)作將觸發(fā)名為’paste’的剪貼板事件,這個(gè)事件的觸發(fā)是在剪貼板里的數(shù)據(jù)插入到目標(biāo)元素之前 。如果目標(biāo)元素(光標(biāo)所在位置)是可編輯的元素(eg:設(shè)置了contenteditable屬性的div 。textarea并不行 。),粘貼動(dòng)作將把剪貼板里的數(shù)據(jù),以最合適的格式 , 插入到目標(biāo)元素里;如果目標(biāo)元素不可編輯,則不會(huì)插入數(shù)據(jù),但依然觸發(fā)paste event 。數(shù)據(jù)在粘貼的過(guò)程中是只讀的 。此段是翻譯于w3.org_the-paste-action ??上У氖?,經(jīng)過(guò)試驗(yàn),發(fā)現(xiàn)chrome(當(dāng)前最新版)、firefox(當(dāng)前最新版)、ie11對(duì)paste事件的實(shí)現(xiàn)并不是完全按照w3c來(lái)的,各自也有區(qū)別(w3c的paste標(biāo)準(zhǔn)也因此只是草案階段) 。
test代碼及截圖如下:
chrome:

textarea /textarea div contenteditable style="width: 100px;height: 100px; border:1px solid" /div script document.addEventListener(’paste’, function (event) {console.log(event) })/scriptevent有clipboardData屬性,且clipboardData有item屬性,clipboardData.item中的元素(對(duì)象)有type和kind屬性;無(wú)論在哪進(jìn)行粘貼,均可觸發(fā)paste事件;在div(未特殊聲明時(shí),本文div均指設(shè)置了contenteditable屬性的div) 里粘貼截圖,不顯示圖片 。img.src為base64編碼字符串;在div里粘貼網(wǎng)頁(yè)圖片,直接顯示圖片,img.src為圖片地址 。【兼容chrome、firefox、ie11 js實(shí)現(xiàn)ctrl v粘貼上傳圖片】firefox:
event有clipboardData屬性,clipboardData沒(méi)有item屬性;只有在textarea里或者可編輯的div(里才粘貼才觸發(fā)paste事件;在div里粘貼截圖,直接顯示圖片,img.src為base64編碼字符串;在div里粘貼網(wǎng)頁(yè)圖片,表現(xiàn)同chrome 。
ie11:(不截圖了 , 可自行試驗(yàn) , 其他瀏覽器同理( ̄▽ ̄)/,因?yàn)閼?..)

event沒(méi)有clipboardData屬性;只在可編輯的div中粘貼才觸發(fā)paste事件;在div里粘貼截圖,直接顯示圖片,img.src為base64編碼字符串;在div里粘貼網(wǎng)頁(yè)圖片,表現(xiàn)同chrome 。
監(jiān)聽(tīng)了paste事件 , 也知道了表現(xiàn)形式 , 接下來(lái)就是如何獲取數(shù)據(jù)了:
chrome有特定的方法,利用clipboardData.items、getAsFile()、new FileReader()等api可以在paste回調(diào)函數(shù)里獲取到剪貼板里圖片的base64編碼字符串(無(wú)論是截圖粘貼的還是網(wǎng)頁(yè)圖片復(fù)制粘貼的) , ie11,firefox沒(méi)有這樣的api , 不過(guò)依然有辦法可以獲取,因?yàn)閿?shù)據(jù)已經(jīng)表現(xiàn)在img的src里了 , 對(duì)于截圖粘貼的,直接取img的src屬性值(base64),對(duì)于網(wǎng)頁(yè)粘貼的 , 則把地址傳給后臺(tái),然后根據(jù)地址down下來(lái),存在自己的服務(wù)器,最后把新地址返回來(lái)交給前端展示就ok了 。為了保持一致性便于管理,統(tǒng)一將所有情況(截圖、網(wǎng)頁(yè))中的img的src屬性替換為自己存儲(chǔ)的地址 。因此可以得到以下核心代碼(注釋很全哦~~):
html展示:
headmeta charset="UTF-8"titleDocument/titlestylebody {display: -webkit-flex;display: flex;-webkit-justify-content: center;justify-content: center;}#tar_box {width: 500px;height: 500px;border: 1px solid red;}/style前端js處理邏輯:
document.addEventListener(’paste’, function (event) {console.log(event)var isChrome = false;if ( event.clipboardData || event.originalEvent ) {//not for ie11某些chrome版本使用的是event.originalEventvar clipboardData = https://www.questions.com.cn/dnjc/(event.clipboardData || event.originalEvent.clipboardData);if ( clipboardData.items ) {// for chromevaritems = clipboardData.items,len = items.length,blob = null;isChrome = true;//items.length比較有意思,初步判斷是根據(jù)mime類型來(lái)的,即有幾種mime類型 , 長(zhǎng)度就是幾(待驗(yàn)證)//如果粘貼純文本,那么len=1,如果粘貼網(wǎng)頁(yè)圖片 , len=2, items[0].type = ’text/plain’, items[1].type = ’image/*’//如果使用截圖工具粘貼圖片,len=1, items[0].type = ’image/png’//如果粘貼純文本 HTML , len=2, items[0].type = ’text/plain’, items[1].type = ’text/html’// console.log(’len:’len);// console.log(items[0]);// console.log(items[1]);// console.log( ’items[0] kind:’, items[0].kind );// console.log( ’items[0] MIME type:’, items[0].type );// console.log( ’items[1] kind:’, items[1].kind );// console.log( ’items[1] MIME type:’, items[1].type );//阻止默認(rèn)行為即不讓剪貼板內(nèi)容在div中顯示出來(lái)event.preventDefault();//在items里找粘貼的image,據(jù)上面分析,需要循環(huán)for (var i = 0; ilen; i) {if (items[i].type.indexOf("image") !== -1) {// console.log(items[i]);// console.log( typeof (items[i]));//getAsFile() 此方法只是living standard firefox ie11 并不支持blob = items[i].getAsFile();}}if ( blob !== null ) {var reader = new FileReader();reader.onload = function (event) {// event.target.result 即為圖片的Base64編碼字符串var base64_str = event.target.result//可以在這里寫上傳邏輯 直接將base64編碼的字符串上傳(可以嘗試傳入blob對(duì)象,看看后臺(tái)程序能否解析)uploadImgFromPaste(base64_str, ’paste’, isChrome);}reader.readAsDataURL(blob);}} else {//for firefoxsetTimeout(function () {//設(shè)置setTimeout的原因是為了保證圖片先插入到div里,然后去獲取值var imgList = document.querySelectorAll(’#tar_box img’),len = imgList.length,src_str = ’’,i;for ( i = 0; ilen; i) {if ( imgList[i].className !== ’my_img’ ) {//如果是截圖那么src_str就是base64 如果是復(fù)制的其他網(wǎng)頁(yè)圖片那么src_str就是此圖片在別人服務(wù)器的地址src_str = imgList[i].src;}}uploadImgFromPaste(src_str, ’paste’, isChrome);}, 1);}} else {//for ie11setTimeout(function () {var imgList = document.querySelectorAll(’#tar_box img’),len = imgList.length,src_str = ’’,i;for ( i = 0; ilen; i) {if ( imgList[i].className !== ’my_img’ ) {src_str = imgList[i].src;}}uploadImgFromPaste(src_str, ’paste’, isChrome);}, 1);}})function uploadImgFromPaste (file, type, isChrome) {var formData = https://www.questions.com.cn/dnjc/new FormData();formData.append(’image’, file);formData.append(’submission-type’, type);var xhr = new XMLHttpRequest();xhr.open(’POST’, ’/upload_image_by_paste’);xhr.onload = function () {if ( xhr.readyState === 4 ) {if ( xhr.status === 200 ) {var data = JSON.parse( xhr.responseText ),tarBox = document.getElementById(’tar_box’);if ( isChrome ) {var img = document.createElement(’img’);img.className = ’my_img’;img.src = data.store_path;tarBox.appendChild(img);} else {var imgList = document.querySelectorAll(’#tar_box img’),len = imgList.length,i;for ( i = 0; ilen; i) {if ( imgList[i].className !== ’my_img’ ) {imgList[i].className = ’my_img’;imgList[i].src = data.store_path;}}}} else {console.log( xhr.statusText );}};};xhr.onerror = function (e) {console.log( xhr.statusText );}xhr.send(formData);}用express.js搭的簡(jiǎn)易后臺(tái)的接收邏輯:
router.post(’/’, upload.array(), function (req, res, next) {//1.獲取客戶端傳來(lái)的src_str字符串=判斷是base64還是普通地址=獲取圖片類型后綴(jpg/png etc)//=如果是base64替換掉"前綴"("data:image/png;base64," etc)//2.base64 轉(zhuǎn)為 buffer對(duì)象 普通地址則先down下來(lái)//3.寫入硬盤(后續(xù)可以將地址存入數(shù)據(jù)庫(kù))//4.返回picture地址var src_str = req.body.image,timestamp = new Date().getTime();if ( src_str.match(/^data:image/png;base64,|^data:image/jpg;base64,|^data:image/jpg;base64,|^data:image/bmp;base64,/) ) {//處理截圖 src_str為base64字符串var pic_suffix = src_str.split(’;’,1)[0].split(’/’,2)[1],base64 = src_str.replace(/^data:image/png;base64,|^data:image/jpg;base64,|^data:image/jpg;base64,|^data:image/bmp;base64,/, ’’),buf = new Buffer(base64, ’base64’),store_path = ’public/images/test_’timestamp’.’pic_suffix;fs.writeFile(store_path, buf, function (err) {if (err) {throw err;} else {res.json({’store_path’: store_path});}});} else {// 處理非chrome的網(wǎng)頁(yè)圖片 src_str為圖片地址var temp_array = src_str.split(’.’),pic_suffix = temp_array[temp_array.length - 1],store_path = ’public/images/test_’timestamp’.’pic_suffix,wstream = fs.createWriteStream(store_path);request(src_str).pipe(wstream);wstream.on(’finish’, function (err) {if( err ) {throw err;} else {res.json({"store_path": store_path});}});}});需要node環(huán)境:安裝node=npm intall=node app.js)

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助 。
您可能感興趣的文章:js兼容火狐顯示上傳圖片預(yù)覽效果的方法上傳圖片js判斷圖片尺寸和格式兼容IEjavascript上傳圖片前預(yù)覽圖片兼容大多數(shù)瀏覽器javascript 客戶端驗(yàn)證上傳圖片的大?。嬡軮E和火狐)JS上傳圖片預(yù)覽插件制作(兼容到IE6)

相關(guān)經(jīng)驗(yàn)推薦