中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

Vue解析剪切板圖片并實現(xiàn)發(fā)送功能

前言

成都創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè)|網(wǎng)站維護|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設(shè)計服務(wù),案例作品覆蓋陽臺護欄等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身制作品質(zhì)網(wǎng)站。

我們在使用QQ進行聊天時,從別的地方Ctrl+C一張圖片,然后在聊天窗口Ctrl+V,QQ就會將你剛才復(fù)制的圖片粘貼到即將發(fā)送的消息容器里,按下Enter鍵,這張圖片將會發(fā)送出去。接下來跟各位開發(fā)者分享下這項功能在Vue中如何來實現(xiàn)。先跟大家展示下最終實現(xiàn)的效果。在線體驗地址

Vue解析剪切板圖片并實現(xiàn)發(fā)送功能

實現(xiàn)思路

  • 頁面掛載時監(jiān)聽剪切板粘貼事件
  • 監(jiān)聽文件流
  • 讀取文件流中的數(shù)據(jù)
  • 創(chuàng)建img標(biāo)簽
  • 將獲取到的base64碼賦值到img標(biāo)簽的src屬性
  • 將生成的img標(biāo)簽append到即將發(fā)送的消息容器里
  • 監(jiān)聽回車事件
  • 獲取可編輯div容器中的所有子元素
  • 遍歷獲取到的元素,找出img元素
  • 判斷當(dāng)前img元素是否有alt屬性(表情插入時有alt屬性),
  • 如果沒有alt屬性當(dāng)前元素就是圖片
  • 將base64格式的圖片轉(zhuǎn)成文件上傳至服務(wù)器
  • 上傳成功后,將服務(wù)器返回的圖片地址推送到websocket服務(wù)
  • 客戶端收到推送后,渲染頁面

實現(xiàn)過程

本片文章主要講解剪切板圖片的解析以及將base64圖片轉(zhuǎn)換成文件上傳至服務(wù)器,下方代碼中的axios的封裝以及websocket的配置與使用可參考我的另外兩篇文章:Vue合理配置axios并在項目中進行實際應(yīng)用和Vue合理配置WebSocket并實現(xiàn)群聊

監(jiān)聽剪切板事件(mounted生命周期中),將圖片渲染到即將發(fā)送到消息容器里

const that = this;
document.body.addEventListener('paste', function (event) {
 // 自己寫的一個全屏加載插件,文章地址:https://juejin.im/post/5e3307145188252c30002fa7
 that.$fullScreenLoading.show("讀取圖片中");
 // 獲取當(dāng)前輸入框內(nèi)的文字
 const oldText = that.$refs.msgInputContainer.textContent;
 // 讀取圖片
 let items = event.clipboardData && event.clipboardData.items;
 let file = null;
 if (items && items.length) {
 // 檢索剪切板items
 for (let i = 0; i < items.length; i++) {
  if (items[i].type.indexOf('image') !== -1) {
  file = items[i].getAsFile();
  break;
  }
 }
 }
 // 預(yù)覽圖片
 const reader = new FileReader();
 reader.onload = function(event) {
 // 圖片內(nèi)容
 const imgContent = event.target.result;
 // 創(chuàng)建img標(biāo)簽
 let img = document.createElement('img');//創(chuàng)建一個img
 // 獲取當(dāng)前base64圖片信息,計算當(dāng)前圖片寬高以及壓縮比例
 let imgObj = new Image();
 let imgWidth = "";
 let imgHeight = "";
 let scale = 1;
 imgObj.src = imgContent;
 imgObj.onload = function() {
  // 計算img寬高
  if(this.width<400){
  imgWidth = this.width;
  imgHeight = this.height;
  }else{
  // 輸入框圖片顯示縮小10倍
  imgWidth = this.width/10;
  imgHeight = this.height/10;
  // 圖片寬度大于1920,圖片壓縮5倍
  if(this.width>1920){
   // 真實比例縮小5倍
   scale = 5;
  }
  }
  // 設(shè)置可編輯div中圖片寬高
  img.width = imgWidth;
  img.height = imgHeight;
  // 壓縮圖片,渲染頁面
  that.compressPic(imgContent,scale,function (newBlob,newBase) {
  // 刪除可編輯div中的圖片名稱
  that.$refs.msgInputContainer.textContent = oldText;
  img.src = newBase; //設(shè)置鏈接
  // 圖片渲染
  that.$refs.msgInputContainer.append(img);
  that.$fullScreenLoading.hide();
  });
 };
 };
 reader.readAsDataURL(file);
});

base64圖片壓縮函數(shù)

 // 參數(shù): base64地址,壓縮比例,回調(diào)函數(shù)(返回壓縮后圖片的blob和base64)
 compressPic:function(base64, scale, callback){
 const that = this;
 let _img = new Image();
 _img.src = base64;
 _img.onload = function() {
  let _canvas = document.createElement("canvas");
  let w = this.width / scale;
  let h = this.height / scale;
  _canvas.setAttribute("width", w);
  _canvas.setAttribute("height", h);
  _canvas.getContext("2d").drawImage(this, 0, 0, w, h);
  let base64 = _canvas.toDataURL("image/jpeg");
  // 當(dāng)canvas對象的原型中沒有toBlob方法的時候,手動添加該方法
  if (!HTMLCanvasElement.prototype.toBlob) {
  Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
   value: function (callback, type, quality) {
   let binStr = atob(this.toDataURL(type, quality).split(',')[1]),
    len = binStr.length,
    arr = new Uint8Array(len);
   for (let i = 0; i < len; i++) {
    arr[i] = binStr.charCodeAt(i);
   }
   callback(new Blob([arr], {type: type || 'image/png'}));
   }
  });
  }else{
  _canvas.toBlob(function(blob) {
   if(blob.size > 1024*1024){
   that.compressPic(base64, scale, callback);
   }else{
   callback(blob, base64);
   }
  }, "image/jpeg");
  }
 }
 }

完善消息發(fā)送函數(shù),獲取輸入框里的所有子元素,找出base64圖片將其轉(zhuǎn)為文件并上傳至服務(wù)器(此處需要注意:base64轉(zhuǎn)文件時,需要用正則表達式刪掉base64圖片的前綴),將當(dāng)前圖片地址推送至websocket服務(wù)。

對下述代碼有不理解的地方,可閱讀我的另一篇文章:Vue實現(xiàn)圖片與文字混輸,

sendMessage: function (event) {
 if (event.keyCode === 13) {
 // 阻止編輯框默認(rèn)生成div事件
 event.preventDefault();
 let msgText = "";
 // 獲取輸入框下的所有子元素
 let allNodes = event.target.childNodes;
 for (let item of allNodes) {
  // 判斷當(dāng)前元素是否為img元素
  if (item.nodeName === "IMG") {
  if (item.alt === "") {
   // 是圖片
   let base64Img = item.src;
   // 刪除base64圖片的前綴
   base64Img = base64Img.replace(/^data:image\/\w+;base64,/, "");
   //隨機文件名
   let fileName = (new Date()).getTime() + ".jpeg";
   //將base64轉(zhuǎn)換成file
   let imgFile = this.convertBase64UrlToImgFile(base64Img, fileName, 'image/jpeg');
   let formData = new FormData();
   // 此處的file與后臺取值時的屬性一樣,append時需要添加文件名,否則一直時blob
   formData.append('file', imgFile, fileName);
   // 將圖片上傳至服務(wù)器
   this.$api.fileManageAPI.baseFileUpload(formData).then((res) => {
   const msgImgName = `/${res.fileName}/`;
   // 消息發(fā)送: 發(fā)送圖片
   this.$socket.sendObj({
    msg: msgImgName,
    code: 0,
    username: this.$store.state.username,
    avatarSrc: this.$store.state.profilePicture,
    userID: this.$store.state.userID
   });
   // 清空輸入框中的內(nèi)容
   event.target.innerHTML = "";
   });
  } else {
   msgText += `/${item.alt}/`;
  }
  } else {
  // 獲取text節(jié)點的值
  if (item.nodeValue !== null) {
   msgText += item.nodeValue;
  }
  }
 }
 // 消息發(fā)送: 發(fā)送文字,為空則不發(fā)送
 if (msgText.trim().length > 0) {
  this.$socket.sendObj({
  msg: msgText,
  code: 0,
  username: this.$store.state.username,
  avatarSrc: this.$store.state.profilePicture,
  userID: this.$store.state.userID
  });
  // 清空輸入框中的內(nèi)容
  event.target.innerHTML = "";
 }
 }
}

base64圖片轉(zhuǎn)flie

// base64轉(zhuǎn)file
convertBase64UrlToImgFile: function (urlData, fileName, fileType) {
 // 轉(zhuǎn)換為byte
 let bytes = window.atob(urlData);
 // 處理異常,將ascii碼小于0的轉(zhuǎn)換為大于0
 let ab = new ArrayBuffer(bytes.length);
 let ia = new Int8Array(ab);
 for (let i = 0; i < bytes.length; i++) {
 ia[i] = bytes.charCodeAt(i);
 }
 // 轉(zhuǎn)換成文件,添加文件的type,name,lastModifiedDate屬性
 let blob = new Blob([ab], {type: fileType});
 blob.lastModifiedDate = new Date();
 blob.name = fileName;
 return blob;
}

axios文件上傳接口的封裝(注意:需要設(shè)置"Content-Type":"multipart/form-data"})
/*
* 文件管理接口
* */
import services from '../plugins/axios'
import base from './base'; // 導(dǎo)入接口域名列表

const fileManageAPI = {
 // 單文件上傳
 baseFileUpload(file){
 return services._axios.post(`${base.lkBaseURL}/uploads/singleFileUpload`,file,{headers:{"Content-Type":"multipart/form-data"}});
 }
};
export default fileManageAPI;

解析websocket推送的消息

// 消息解析
messageParsing: function (msgObj) {
 // 解析接口返回的數(shù)據(jù)并進行渲染
 let separateReg = /(\/[^/]+\/)/g;
 let msgText = msgObj.msgText;
 let finalMsgText = "";
 // 將符合條件的字符串放到數(shù)組里
 const resultArray = msgText.match(separateReg);
 if (resultArray !== null) {
  for (let item of resultArray) {
   // 刪除字符串中的/符號
   item = item.replace(/\//g, "");
   // 判斷是否為圖片: 后綴為.jpeg
   if(this.isImg(item)){
    // 解析為img標(biāo)簽
    const imgTag = `<img src="${base.lkBaseURL}/upload/image/${item}" alt="聊天圖片">`;
    // 替換匹配的字符串為img標(biāo)簽:全局替換
    msgText = msgText.replace(new RegExp(`/${item}/`, 'g'), imgTag);
   }
  }
  finalMsgText = msgText;
 } else {
  finalMsgText = msgText;
 }
 msgObj.msgText = finalMsgText;
 // 渲染頁面
 this.senderMessageList.push(msgObj);
 // 修改滾動條位置
 this.$nextTick(function () {
  this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
 });
}

判斷當(dāng)前字符串是否為有圖片后綴

// 判斷是否為圖片
isImg: function (str) {
 let objReg = new RegExp("[.]+(jpg|jpeg|swf|gif)$", "gi");
 return objReg.test(str);
}

踩坑記錄

直接將base64格式的圖片通過websocket發(fā)送至服務(wù)端

結(jié)果很明顯,服務(wù)端websocket服務(wù)報錯,報錯原因:內(nèi)容超過最大長度。

前端通過post請求將base64碼傳到服務(wù)端,服務(wù)端直接將base64碼解析為圖片保存至服務(wù)器

從下午2點折騰到晚上6點,一直在找Java解析base64圖片存到服務(wù)器的方案,最終選擇了放棄,采用了前端轉(zhuǎn)換方式,這里的問題大概是前端傳base64碼到后端時,http請求會進行轉(zhuǎn)義,導(dǎo)致后端解析得到的base64碼是錯誤的,所以一直沒有成功。

項目地址:chat-system

總結(jié)

以上所述是小編給大家介紹的Vue解析剪切板圖片并實現(xiàn)發(fā)送功能,希望對大家有所幫助!

標(biāo)題名稱:Vue解析剪切板圖片并實現(xiàn)發(fā)送功能
鏈接URL:http://www.rwnh.cn/article48/gdihep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版軟件開發(fā)、品牌網(wǎng)站建設(shè)、外貿(mào)建站、網(wǎng)站設(shè)計公司、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)
汕头市| 柘荣县| 彩票| 双辽市| 东源县| 阳朔县| 泾源县| 凌源市| 怀化市| 通道| 张家口市| 丽江市| 韶山市| 邵武市| 罗源县| 梅河口市| 安陆市| 鄢陵县| 大厂| 监利县| 神农架林区| 贵德县| 株洲县| 乌鲁木齐市| 轮台县| 钦州市| 临西县| 苗栗县| 宁安市| 石河子市| 鄂尔多斯市| 石渠县| 温宿县| 宝兴县| 宜黄县| 会理县| 新巴尔虎右旗| 安顺市| 肇庆市| 徐水县| 临朐县|