clipboardData

  起因:应项目需求,需要用某个工具截图然后粘贴上传到后台的功能!于是着手搜查资料,最终的结果就是找到了这个对象clipboardData,然后开始着手!

谷歌chrome浏览器测试(clipboardData)

相信这个也是很多开发者都在用的浏览器,当然也是尝试的开始。整个过程是这样的
1)使用微信截图
2)'⌘+v, ctrl+v'在这个页面的随意位置粘贴
3)执行上传图片到后台的流程(产生loading状态)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
document.body.addEventListener('paste', files, false)
// files是一个方法,里面的参数为event
function files(event) {
// 谷歌浏览器的的粘贴文件在这个对象下面

if (event.clipboardData || event.originalEvent) {
var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);

// 获取文件的属性就在这里获取,打印该对象可以看到相关属性,结果的操作就在items里面,所以需要循环items
let fileObj = null;
for (var i = 0; i < len; i++) {
// console.log(items[i]);
if (items[i].type.indexOf("image") !== -1) {
// getAsFile() 此方法只是该浏览器下才会有的方法
fileObj = items[i].getAsFile();
}
}
if(fileObj !== null) {
fileObj就是一个文件对象,此刻就可以进行文件的处理了,例如用formdata的形式传递给后台,这个自行百度,本片章不与讲述。
}


}

}

如果需要在页面中显示可以有两种方法显示图片

第一种:在上面的代码if处接着写

1
2
3
4
5

if(fileObj !== null) {
var fileUrl=URL.createObjectURL(blob); // URL是一个公用的对象
document.getElementById("imgNode").src=fileUrl;
}

第二种方法是用base64的方法可以实现, 需要借助FileReader对象

1
2
3
4
5
6
7
var reader = new FileReader();
reader.onload = function (event) {
//event.target.result 即为图片的Base64编码字符串
var base64_str = event.target.result;
document.getElementById("imgNode").src=base64_str;
}
reader.readAsDataURL(blob);

  以上就是在谷歌浏览器中实现的方法了!但是仅限在谷歌浏览器,因为此项目在mac上开发,所以就尝试了在safari中试着运行,结果一点反应都没有,哎,相继查了很多的资料才懂了一点点,这里也就简单的分享下,希望对这一块比较有深入了解的人来评论、指导下我。

疑问

  document.body下的onpaste不起作用,现在也没有查到,于是乎只能在div(contenteditable)下尝试了一下下。但是发现clipboardData下面并没有items这个对象,所以上面的方法也就不成立了,具体的哪些数据可以参考 这篇文章,上面介绍了他属性的一些要求,所以只能另谋方法了!查阅了好多资料明白了一些!safari粘贴的数据根本就没有存在clipboardData这个对象下,而是在这个div下添加了一个图片,新建了一个img标签,然后src指向本地的 blob链接数据,不信的话你们可以自己打印一下。所以想要获取对象只能这样了,具体代码如下,借助jq

base64转换为blob对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function dataURLtoBlob(dataURL, sliceSize) {
var b64Data, byteArray, byteArrays, byteCharacters, byteNumbers, contentType, i, m, offset, ref, slice;
if (sliceSize == null) {
sliceSize = 512;
}
if (!(m = dataURL.match(/^data\:([^\;]+)\;base64\,(.+)$/))) {
return null;
}
ref = m, m = ref[0], contentType = ref[1], b64Data = ref[2];
byteCharacters = atob(b64Data);
byteArrays = [];
offset = 0;
while (offset < byteCharacters.length) {
slice = byteCharacters.slice(offset, offset + sliceSize);
byteNumbers = new Array(slice.length);
i = 0;
while (i < slice.length) {
byteNumbers[i] = slice.charCodeAt(i);
i++;
}
byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
offset += sliceSize;
}
return new Blob(byteArrays, {
type: contentType
});
};

base64 转为 文件对象

1
2
3
4
5
6
7
8
function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}

##查找浏览器添加的图片标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var _checkImagesInContainer = function(that,cb) {
var img, j, len, ref, timespan;
timespan = Math.floor(1000 * Math.random());

ref = that.find('img');
for (j = 0, len = ref.length; j < len; j++) {
img = ref[j];
img["_paste_marked_" + timespan] = true;
}
return setTimeout((function(_this) {
return function() {
var k, len1, ref1;
ref1 = _this.find('img');
for (k = 0, len1 = ref1.length; k < len1; k++) {
img = ref1[k];
if (!img["_paste_marked_" + timespan]) {
cb(img.src);
$(img).remove();
}
}
};
})(that), 1);
};

##结果运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
_handleImage = function(src, e, name) {
var loader;
loader = new Image();
loader.crossOrigin = "anonymous";
loader.onload = (function(_this) {
return function() {
var blob, canvas, ctx, dataURL;
canvas = document.createElement('canvas');
canvas.width = loader.width;
canvas.height = loader.height;
ctx = canvas.getContext('2d');
ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
dataURL = null;
try {
dataURL = canvas.toDataURL('image/png'); //使用这个图片的时候需要加入这个属性crossOrigin,因为需要开启允许跨域
blob = dataURLtoBlob(dataURL);
console.log(dataURLtoFile(dataURL, 'test'))
} catch (error) {}
if (dataURL) {
// _this._target.trigger('pasteImage', {
// blob: blob,
// dataURL: dataURL,
// width: loader.width,
// height: loader.height,
// originalEvent: e,
// name: name
// });
}
};
})(this);
return loader.src = src;
};
<div class="input" contenteditable></div>
$('.input').on('paste', function (event) {
_checkImagesInContainer($('.input'), function (src) {
_handleImage(src, $('.input'))
})

})

  • 补充一些点,最后的方法在解释下:
    找到img标签,那会blob的本地数据,然后用canvas处理得到base64的数据,然后渲染给图片,如果需要文件就需要多走两部,第一步是将dataUrl转换为blob对象,blob在转为文件对象!然后就可以按照自己的习惯(formdata)传递给后台了!
Jeremy wechat
欢迎您扫一扫上面的微信公众号,订阅我的公众号!