粘贴和拖拽上传图片 - ZJH9Rondo/Blog-Node GitHub Wiki

本项目如何开发及使用

  • 由于浏览器对于粘贴事件的支持程度不同,所以在此处根据在js高程中的学习,加入了一个简单的浏览器客户端检测,根据当前检测的返回结果创建tips,表明当前用户所在的浏览器支持什么操作。

下面两张图片就是在不同的浏览器中打开后所展示的不同提示,这样能再一定程度上很好的避免用户出现误操作出现无响应等情况,倒置用户误以为当前页面无法执行复制粘贴上传的操作。

Chrome tips

Firefox tips

粘贴上传图片

  • 对于粘贴上传图片利用了对于paste事件中的clipboardData属性,当在执行复制操作后,该属性中保存着一个DataTransfer对象,在clipboardData中存储着由paste事件处理器拷贝进剪切板的数据,对于不同类型的数据类型在clipboardData.item[i].kind中可以进行获取,通过js判断当前所在clipboardData中的数据是否为我们所需的数据而进行相应的操作。
 for(var i = 0,len = clipboardData.items.length;i < len; i++){
        if(clipboardData.items[i].kind == 'file' || clipboardData.items[i].type.indexOf('image') > -1){
          imageFile = clipboardData.items[i].getAsFile();
        }else if(clipboardData.items[i].kind == 'string' || clipboardData.items[i].type.indexOf('text') > -1){
          var text = clipboardData.getData('text/plain') || clipboardData.getData('text');

          createform.value = createform.value.substring(0,createform.selectionStart) + text + createform.value.substring(createform.selectionEnd,createform.value.length);

          createform.selectionStart = createform.selectionEnd = createform.selectionStart + text.length; //移动光标
        }
      }

  这里需要提到的一点是,当你进行粘贴操作时,一般在clipboardData中的数据不止一个,需要遍历(具体为什么,还没有找到一个说明,MDN官方文档没有说明,后续我找到后会更新此处说明,如果您觉得有需要补充的,欢迎更正),通过对遍历对象的遍历,对每个clipboardData.item[i].kind判断进行操作。

  而这里使用了getAsFile()方法和getData()方法,这并不是属于clipboardData内置属性的,而是在clipboardData中有一个内置对象,就是上文提到的DataTransfer对象的,我们可以使用其取出由paste事件获取的数据。      这里在一开始的时候由于对文本输入框绑定了paste事件,导致原本的文本粘贴事件冲突,所以加入了   对Text/Plain的判断,而后续的selectionStart和selectionEnd是为了满足在复制操作插入操作之后修正光标位置,将其移动至当前文本末尾。

  需要补充一点的是,clipboardData在IE中与其他浏览器是不同的,在代码中也做了判断和处理。

 var clipboardData = e.clipboardData || window.clipboardData; // clipboardData chrome,firefox || IE

这里,可以根据浏览器的不同,能尽可能的保证获取到所需的对应的对象,但是这个功能在MDN文档中做了说明,该功能还不是标准,所以在各大浏览器不同版本可能效果有所不同,上述更改已经尽可能做到了满足此功能的使用。

拖拽上传图片

  • 当前拖拽上传图片限于本地图片文件拖拽上传,并且一次仅限于拖拽一张图片上传(后续会加入批量拖拽上传)

  • 这里是利用了HTML5的drag和drop属性,但是兼容性只是对于现代浏览器,当然,你都用Github了,我不信你的浏览器还是远古时代的装备,如果是,那当我没说。

  首先,需要阻止其默认事件,例如刚拖入时,以及在目标区域拖动时的一系列默认事件

  createform.addEventListener('dragstart',function (e){
      e = e || window.event;

      e.preventDefault();
    },false);

    createform.addEventListener('dragenter',function (e){
      e = e || window.event;

      e.preventDefault();
    },false);

    createform.addEventListener('dragover',function (e){
      e = e || window.event;

      e.preventDefault();
    },false);

当出现drop操作时,即可对当前在事件内置对象dataTransfer对象中的数据进行操作,在dataTransfer.files中储存着当前数据,其是一个数组,因为当前是单一文件拖拽,所以不用进行遍历

  createform.addEventListener('drop',function (e){
      e = e || window.event;

      e.preventDefault();
      // get filelist
      var fileList = e.dataTransfer.files;
      if(fileList.length === 0 || fileList[0].type.indexOf('image') === -1){
        var tips_drag = '请拖入正确数量本地图片文件';

        navigator_off(tips_drag);
        return;
      }
      
     // 这里,直接将其数据传入上传函数
      getToken(fileList[0]);
    },false);

对于文件上传的处理

  • 由于这里上传选择的是base64客户端直传方式,所以我们需要获取当前获得的图片的base64编码,直接将其上传

  • 这里使用了HTML5提供的FileReader()对象,其提供的readAsDataURL(),它会读取我们在之前获取到的File对象,当获取完成后,会触发onload事件,执行相应的操作,而此时通过获取传入的event对象的target.result,然后得到的就是64位格式编码,并且,在直传时,七牛要求附带所要上传的图片的原始的size,也就是我们获取的File对象的size属性的值,这就是当前图片的原始size。

  var reader = new FileReader();
        // event.target.result === Img Base64_code
        function upload_Item(img_origin,token){
          reader.readAsDataURL(img_origin);

          reader.onload = function (event){
            var base64_str = event.target.result,
                upload_url,
                UpToken;

            base64_str = base64_str.replace(/^data:image\/\w+;base64,/, '');
            // 测试链接
            upload_url = 'http://upload.qiniu.com/putb64/' + img_origin.size;
            UpToken = token;
            // upload Image
            upload_base64(base64_str,upload_url,UpToken);
         };
        }

  此时,在获取了对应的所需图片数据资源后,即可调取后台接口获取七牛图床返回的上传token,然后直接用ajax携带图片信息及token上传即可,也就是上边代码中的upload_base64()函数,由于指定了所需的返回值为图片在图床的访问URL,所以将其使用js转换为Markdown格式,将其插入正在编辑的文本框。

  function markdown_IMG(Imgsrc){
      var selectionStart = createform.selectionStart,
          selectionEnd = createform.selectionEnd,
          selectionText = createform.value,
          insert_Img;

      insert_Img = '![MyBlog](' + Imgsrc +')'; // markdown 语法插入图片
      createform.value = selectionText.substring(0,selectionStart) + insert_Img + selectionText.substring(selectionEnd,selectionText.length);
      selectionStart = selectionEnd = selectionStart + insert_Img.length; //移动光标
    }
  • 至此,拖拽和粘贴上传图片的流程介绍大概就完成了,具体细节操作及逻辑,可在代码中具体查看,其中知识点的分析限于个人使用及总结,望指正。