粘贴和拖拽上传图片 - ZJH9Rondo/Blog-Node GitHub Wiki
本项目如何开发及使用
- 由于浏览器对于粘贴事件的支持程度不同,所以在此处根据在js高程中的学习,加入了一个简单的浏览器客户端检测,根据当前检测的返回结果创建tips,表明当前用户所在的浏览器支持什么操作。
下面两张图片就是在不同的浏览器中打开后所展示的不同提示,这样能再一定程度上很好的避免用户出现误操作出现无响应等情况,倒置用户误以为当前页面无法执行复制粘贴上传的操作。
Chrome
Firefox
粘贴上传图片
- 对于粘贴上传图片利用了对于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; //移动光标
}
- 至此,拖拽和粘贴上传图片的流程介绍大概就完成了,具体细节操作及逻辑,可在代码中具体查看,其中知识点的分析限于个人使用及总结,望指正。