Node.js——微信聊天圖片發(fā)送功能實現(xiàn)

圖片實現(xiàn)功能分瀏覽器實現(xiàn)

這次主要要寫如何通過右鍵粘貼獲得截圖(沒錯,就是QQ截圖)以及網(wǎng)絡(luò)圖片

chrome

$("body").on('paste','.emoji-wysiwyg-editor',function(event){

        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        //chrome提供了直接獲取剪切板上內(nèi)容的API,有的chrome瀏覽器是event.clipboardData,有的則是event.originalEvent.clipboardData
        if ( clipboardData.items ) {
            var  items = clipboardData.items,
                len = items.length,
            //如果粘貼純文本,那么len=1,如果粘貼網(wǎng)頁圖片,len=2, items[0].type = 'text/plain', items[1].type = 'image/*'
            //如果使用截圖工具粘貼圖片,len=1, items[0].type = 'image/png'
                blob = null;

            for (var i = 0; i < len; i++) {
                console.log(items[i]);
                console.log( items[i].type);
                if (items[i].type.indexOf("image") !== -1) {
                    event.preventDefault();
                    blob = items[i].getAsFile();
                    //blob就是需要上傳到服務(wù)器的內(nèi)容
                }
            }
            console.log(blob);
            if ( blob !== null ) {
                var reader = new FileReader();
                reader.onload = function (event) {
                //文件讀取成功完成時觸發(fā)
                    // event.target.result 即為圖片的Base64編碼字符串
                    var base64_str = event.target.result;
                    //console.log(base64_str);
                    //根據(jù)后端服務(wù)器來選擇上傳base64的編碼或者直接上傳blob對象
                    doUpload(blob);
                }
                reader.readAsDataURL(blob);
                //該方法將文件讀取為一段以 data: 開頭的字符串,這段字符串的實質(zhì)就是 Data URL,Data URL是一種將小文件直接嵌入文檔的方案。這里的小文件通常是指圖像與 html 等格式的文件。
            }
       }

})


//ajax

function doUpload(file) {

    $(".pg-wrapper").show();

    var file = file;
    //獲取img的后綴,png、jpg等
    console.log(file.type);
    var form = new FormData();
    form.append("file", file);
    form.append("filetype",file.type);
    console.log(form);

    $.ajax({
        url: "/uploadImg",
        type: "POST",
        data: form,
        async: true,
        processData: false,
        contentType: false,
        success: function(result) {
            $.Insertimage(result.data);
            //圖片上傳到服務(wù)器后臺成功后返回圖片的地址,Insetimage用于插入圖片
        }
    });
        //$.Insertimage補(bǔ)充于jquery-emojirea.js這個閉包函數(shù)中
        $.Insertimage= function (url) {
        if (CONST.hasFocus) {
            CONST.selection = util.saveSelection();
                        //CONST指向EmojiArea_WYSIWYG(上一篇文章提過,這個函數(shù)寫在jquery-emojirea.js這個閉包函數(shù)中)
                        //如果文本編輯框div被處于focus狀態(tài),則調(diào)用 util.saveSelection()函數(shù)獲取當(dāng)前光標(biāo)對象并復(fù)制給CONST.selection
        }
        var $img = $(EmojiArea.createImage(url));
                //將url包裝成為<img src=url>的格式
        if ($img[0].attachEvent) {
            $img[0].attachEvent('onresizestart', function(e) { e.returnValue = false; }, false);
        }
        console.dir(CONST.$editor+"這里是const");
        CONST.$editor.trigger('focus');
        if (CONST.selection) {
            util.restoreSelection(CONST.selection);
                        //將文本編輯框的selection(也可以是歷史記錄)存入util中,設(shè)置當(dāng)前selection為CONST.selection
        }
        try { util.replaceSelection($img[0]); } catch (e) {}
                //對光標(biāo)部分進(jìn)行替換
        CONST.onChange();
                //onChange方法用于將div的內(nèi)容賦值給對應(yīng)的textarea中
    }

}

對應(yīng)后臺程序

后臺用的是Node.js以及express

var formidable = require('formidable');
var fs = require('fs');
router.post('/uploadImg', function(req, res, next) {

  var io = global.io;
//var io = require('socket.io').listen(server);global.io = io;,io是全局變量

  var form = new formidable.IncomingForm();
  var path = "";
  var fields = [];

  form.encoding = 'utf-8';
  form.uploadDir = "upload";
  form.keepExtensions = true;
  form.maxFieldsSize = 30000 * 1024 * 1024;


  var uploadprogress = 0;
  //console.log("start:upload----"+uploadprogress);

  form.parse(req);

  form.on('field', function(field, value) {
    fields[field] = value;
    //主要用于存儲filetype
  })
      .on('file', function(field, file) {
        path = '\\' + file.path;
        if(fields['filetype'].match(/image/)){
          var str = fields['filetype'].match(/[^image\/]\w+$/);//提取image/后面部分的圖片后綴
          var str = str[0];
          var reg = new RegExp(str);
          if(!file.path.match(reg)){
          //如果file的路徑不含圖片后綴則執(zhí)行以下操作
            fs.rename(file.path,file.path+'.'+str, function(err){
              if(err){
                throw err;
              }
              console.log('done!');
              path = '\\' + file.path+'.'+str;
            })
          }else{
            path = '\\' + file.path;
          }
        }else{
          path = '\\' + file.path;
        }



      })
      .on('progress', function(bytesReceived, bytesExpected) {

        uploadprogress = (bytesReceived / bytesExpected * 100).toFixed(0);
        //console.log("upload----"+ uploadprogress);
        io.sockets.in('sessionId').emit('uploadProgress', uploadprogress);
      })
      .on('end', function() {

        //console.log('-> upload done\n');
        entries.code = 0;

        if(fields['filetype'].match(/image/)){
          var str = fields['filetype'].match(/[^image\/]\w+$/);
          var str = str[0];
          var reg = new RegExp(str);
          if(!path.match(reg)){
            path = path + '.' + str;
          }
        }//再次檢查path是否正確(其實上面一段檢查并沒有什么卵用)


        entries.data = path;
        res.writeHead(200, {
          'content-type': 'text/json'
        });
        res.end(JSON.stringify(entries));//將圖片地址作為json數(shù)據(jù)傳送到前臺
      })
      .on("err",function(err){
        var callback="<script>alert('"+err+"');</script>";
        res.end(callback);//這段文本發(fā)回前端就會被同名的函數(shù)執(zhí)行
      }).on("abort",function(){
    var callback="<script>alert('"+ttt+"');</script>";
    res.end(callback);
  });

});

firefox

$("body").on('paste','.emoji-wysiwyg-editor',function(event){
           setTimeout(function () {
                //設(shè)置setTimeout的原因是為了保證圖片先插入到div里,然后去獲取值
                $(".emoji-wysiwyg-editor img").each(function () {
                    if($(this).attr("src").toString().match(/base64/)){//火狐瀏覽器不提供獲取clipboard內(nèi)容的api,但是允許粘貼圖片到可編輯的div中,粘貼后的圖片的src是base64編碼的形式,可將其上傳到服務(wù)器
                        var base64_str = $(this).attr("src");
                        doUploadFF(base64_str);
                    }else if($(this).attr("alt")===undefined||!$(this).attr("alt").toString().match(/^:.+:$/))
                    {
                        var base64_str = $(this).attr("src");
                        doUploadFF(base64_str);
                    }
                    //兩個if語句第一個用于獲取截圖的到的本地圖片,第二個用于獲取網(wǎng)頁上的圖片復(fù)制過來的,貌似沒差
                })
            }, 1);
})
//ajax
function doUploadFF(base64_str) {

    console.log(base64_str);

    $.ajax({
        url: "/uploadImgFF",
        type: "POST",
        data:JSON.stringify({
            'base64':base64_str,
        }),
        async: true,
        processData: false,
        contentType:"application/json",
        success: function(result) {
            console.log(result.store_path);
            //$.Insetimage(result.data);
            $(".emoji-wysiwyg-editor img").each(function () {
                if($(this).attr("src").toString().match(/base64/)){
                    $(this).attr({src:result.store_path,alt:":"+result.store_path+":"});
                    $(this).addClass("Notemoji");
                    $.constChange();
                }else if($(this).attr("alt")===undefined||!$(this).attr("alt").toString().match(/^:.+:$/))
                {
                    $(this).attr({src:result.store_path,alt:":"+result.store_path+":"});
                    $(this).addClass("Notemoji");
                    $.constChange();
                }
            })
        }
    });
}

后臺

router.post('/uploadImgFF',function (req,res,next) {
  //1.獲取客戶端傳來的src_str字符串=>判斷是base64還是普通地址=>獲取圖片類型后綴(jpg/png etc)
//=>如果是base64替換掉"前綴"("data:image\/png;base64," etc)
//2.base64 轉(zhuǎn)為 buffer對象 普通地址則先down下來
//3.寫入硬盤(后續(xù)可以將地址存入數(shù)據(jù)庫)
//4.返回picture地址

  var src_str = req.body.base64,
      timestamp = new Date().getTime();
  console.log(src_str);

  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 = './upload/' + timestamp + '.' + pic_suffix;
        console.log(store_path);

    fs.writeFile(store_path, buf, function (err) {
      if (err) {
        throw err;
      } else {
        res.json({'store_path': store_path});
      }
  });
} else {
  console.log("網(wǎng)頁圖片"+src_str);
  var temp_array = src_str.split('.'),
      pic_suffix = temp_array[temp_array.length - 1],
      store_path = './upload/' + timestamp + '.' + pic_suffix,
      wstream = fs.createWriteStream(store_path);
  console.log(store_path);
  request(src_str).pipe(wstream);
  wstream.on('finish', function (err) {
    console.log("進(jìn)入finish");
    if( err ) {
      throw err;
    } else {
      res.json({'store_path': store_path});
    }
  });


}
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,979評論 25 709
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實...
    香橙柚子閱讀 24,735評論 8 183
  • 小時候,在紅薯剛剛可以吃的時候,我們就鬧騰著要吃。于是父母有時候上地里干活回來,會扒上幾個拿回家,給我們嘗鮮。其實...
    楓紅云天閱讀 1,018評論 20 14
  • 實現(xiàn)后臺自動生成文檔,減少前后臺溝通成本。spring mvc與swagger的集成 1. 下載https://g...
    晨宇閱讀 1,572評論 2 2
  • 陳元達(dá)反對劉聰修建昭儀殿,他估計肯定要出事,所以拿鎖把自己鎖起來。這就是,有孚,血去惕出,無咎。通過鎖起來搏一把,...
    Nuckyli閱讀 191評論 0 0

友情鏈接更多精彩內(nèi)容