bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

Vue解析剪切板圖片并實現發送功能

前言

成都創新互聯公司專注于網站建設|網站維護|優化|托管以及網絡推廣,積累了大量的網站設計與制作經驗,為許多企業提供了網站定制設計服務,案例作品覆蓋陽臺護欄等行業。能根據企業所處的行業與銷售的產品,結合品牌形象的塑造,量身制作品質網站。

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

Vue解析剪切板圖片并實現發送功能

實現思路

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

實現過程

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

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

const that = this;
document.body.addEventListener('paste', function (event) {
 // 自己寫的一個全屏加載插件,文章地址:https://juejin.im/post/5e3307145188252c30002fa7
 that.$fullScreenLoading.show("讀取圖片中");
 // 獲取當前輸入框內的文字
 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;
  }
 }
 }
 // 預覽圖片
 const reader = new FileReader();
 reader.onload = function(event) {
 // 圖片內容
 const imgContent = event.target.result;
 // 創建img標簽
 let img = document.createElement('img');//創建一個img
 // 獲取當前base64圖片信息,計算當前圖片寬高以及壓縮比例
 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;
  }
  }
  // 設置可編輯div中圖片寬高
  img.width = imgWidth;
  img.height = imgHeight;
  // 壓縮圖片,渲染頁面
  that.compressPic(imgContent,scale,function (newBlob,newBase) {
  // 刪除可編輯div中的圖片名稱
  that.$refs.msgInputContainer.textContent = oldText;
  img.src = newBase; //設置鏈接
  // 圖片渲染
  that.$refs.msgInputContainer.append(img);
  that.$fullScreenLoading.hide();
  });
 };
 };
 reader.readAsDataURL(file);
});

base64圖片壓縮函數

 // 參數: base64地址,壓縮比例,回調函數(返回壓縮后圖片的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");
  // 當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");
  }
 }
 }

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

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

sendMessage: function (event) {
 if (event.keyCode === 13) {
 // 阻止編輯框默認生成div事件
 event.preventDefault();
 let msgText = "";
 // 獲取輸入框下的所有子元素
 let allNodes = event.target.childNodes;
 for (let item of allNodes) {
  // 判斷當前元素是否為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轉換成file
   let imgFile = this.convertBase64UrlToImgFile(base64Img, fileName, 'image/jpeg');
   let formData = new FormData();
   // 此處的file與后臺取值時的屬性一樣,append時需要添加文件名,否則一直時blob
   formData.append('file', imgFile, fileName);
   // 將圖片上傳至服務器
   this.$api.fileManageAPI.baseFileUpload(formData).then((res) => {
   const msgImgName = `/${res.fileName}/`;
   // 消息發送: 發送圖片
   this.$socket.sendObj({
    msg: msgImgName,
    code: 0,
    username: this.$store.state.username,
    avatarSrc: this.$store.state.profilePicture,
    userID: this.$store.state.userID
   });
   // 清空輸入框中的內容
   event.target.innerHTML = "";
   });
  } else {
   msgText += `/${item.alt}/`;
  }
  } else {
  // 獲取text節點的值
  if (item.nodeValue !== null) {
   msgText += item.nodeValue;
  }
  }
 }
 // 消息發送: 發送文字,為空則不發送
 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
  });
  // 清空輸入框中的內容
  event.target.innerHTML = "";
 }
 }
}

base64圖片轉flie

// base64轉file
convertBase64UrlToImgFile: function (urlData, fileName, fileType) {
 // 轉換為byte
 let bytes = window.atob(urlData);
 // 處理異常,將ascii碼小于0的轉換為大于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);
 }
 // 轉換成文件,添加文件的type,name,lastModifiedDate屬性
 let blob = new Blob([ab], {type: fileType});
 blob.lastModifiedDate = new Date();
 blob.name = fileName;
 return blob;
}

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

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) {
 // 解析接口返回的數據并進行渲染
 let separateReg = /(\/[^/]+\/)/g;
 let msgText = msgObj.msgText;
 let finalMsgText = "";
 // 將符合條件的字符串放到數組里
 const resultArray = msgText.match(separateReg);
 if (resultArray !== null) {
  for (let item of resultArray) {
   // 刪除字符串中的/符號
   item = item.replace(/\//g, "");
   // 判斷是否為圖片: 后綴為.jpeg
   if(this.isImg(item)){
    // 解析為img標簽
    const imgTag = `<img src="${base.lkBaseURL}/upload/image/${item}" alt="聊天圖片">`;
    // 替換匹配的字符串為img標簽:全局替換
    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;
 });
}

判斷當前字符串是否為有圖片后綴

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

踩坑記錄

直接將base64格式的圖片通過websocket發送至服務端

結果很明顯,服務端websocket服務報錯,報錯原因:內容超過最大長度。

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

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

項目地址:chat-system

總結

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

標題名稱:Vue解析剪切板圖片并實現發送功能
鏈接URL:http://vcdvsql.cn/article48/gdihep.html

成都網站建設公司_創新互聯,為您提供網站改版、軟件開發品牌網站建設、外貿建站、網站設計公司、靜態網站

廣告

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

營銷型網站建設