美文网首页前端社团
Node.js——微信聊天图片发送功能实现

Node.js——微信聊天图片发送功能实现

作者: 折柳画马 | 来源:发表于2016-10-31 20:48 被阅读164次

图片实现功能分浏览器实现

这次主要要写如何通过右键粘贴获得截图(没错,就是QQ截图)以及网络图片

chrome

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

        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        //chrome提供了直接获取剪切板上内容的API,有的chrome浏览器是event.clipboardData,有的则是event.originalEvent.clipboardData
        if ( clipboardData.items ) {
            var  items = clipboardData.items,
                len = items.length,
            //如果粘贴纯文本,那么len=1,如果粘贴网页图片,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就是需要上传到服务器的内容
                }
            }
            console.log(blob);
            if ( blob !== null ) {
                var reader = new FileReader();
                reader.onload = function (event) {
                //文件读取成功完成时触发
                    // event.target.result 即为图片的Base64编码字符串
                    var base64_str = event.target.result;
                    //console.log(base64_str);
                    //根据后端服务器来选择上传base64的编码或者直接上传blob对象
                    doUpload(blob);
                }
                reader.readAsDataURL(blob);
                //该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 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);
            //图片上传到服务器后台成功后返回图片的地址,Insetimage用于插入图片
        }
    });
        //$.Insertimage补充于jquery-emojirea.js这个闭包函数中
        $.Insertimage= function (url) {
        if (CONST.hasFocus) {
            CONST.selection = util.saveSelection();
                        //CONST指向EmojiArea_WYSIWYG(上一篇文章提过,这个函数写在jquery-emojirea.js这个闭包函数中)
                        //如果文本编辑框div被处于focus状态,则调用 util.saveSelection()函数获取当前光标对象并复制给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中,设置当前selection为CONST.selection
        }
        try { util.replaceSelection($img[0]); } catch (e) {}
                //对光标部分进行替换
        CONST.onChange();
                //onChange方法用于将div的内容赋值给对应的textarea中
    }

}

对应后台程序

后台用的是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的路径不含图片后缀则执行以下操作
            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数据传送到前台
      })
      .on("err",function(err){
        var callback="<script>alert('"+err+"');</script>";
        res.end(callback);//这段文本发回前端就会被同名的函数执行
      }).on("abort",function(){
    var callback="<script>alert('"+ttt+"');</script>";
    res.end(callback);
  });

});

firefox

$("body").on('paste','.emoji-wysiwyg-editor',function(event){
           setTimeout(function () {
                //设置setTimeout的原因是为了保证图片先插入到div里,然后去获取值
                $(".emoji-wysiwyg-editor img").each(function () {
                    if($(this).attr("src").toString().match(/base64/)){//火狐浏览器不提供获取clipboard内容的api,但是允许粘贴图片到可编辑的div中,粘贴后的图片的src是base64编码的形式,可将其上传到服务器
                        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语句第一个用于获取截图的到的本地图片,第二个用于获取网页上的图片复制过来的,貌似没差
                })
            }, 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 转为 buffer对象 普通地址则先down下来
//3.写入硬盘(后续可以将地址存入数据库)
//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("网页图片"+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("进入finish");
    if( err ) {
      throw err;
    } else {
      res.json({'store_path': store_path});
    }
  });


}
})

相关文章

网友评论

    本文标题:Node.js——微信聊天图片发送功能实现

    本文链接:https://www.haomeiwen.com/subject/ibpputtx.html