这是《大胖小课》栏目的专题一《说说文件上传那些事儿》的第5节-《实现文件拖拽和剪贴板上传》
专题已经更新章节:
html5
的出现,让拖拽上传交互成为可能,现在这样的体验也屡见不鲜,实现上也比较简单。
主要是先定义好一个拖拽区域,从该拖拽区域的事件回调内得到文件的相关信息,前提是需要取消一些事件的默认行为,因为浏览器本身会自动打开或下载文件。
DEMO
说明
div.drop-box
drop
事件的默认行为e.preventDefault();
,不然浏览器会直接打开文件dragover
, 鼠标离开拖拽区域dragleave
, 在拖拽区域上释放文件drop
drop
事件内获得文件信息e.dataTransfer.files
HTML
<div class="drop-box" id="drop-box">
拖动文件到这里,开始上传
</div>
<button type="button" id="btn-submit">上 传</button>
JS
<script>
var box = document.getElementById('drop-box');
//禁用浏览器的拖放默认行为
document.addEventListener('drop',function (e) {
console.log('document drog');
e.preventDefault();
});
//设置拖拽事件
function openDropEvent() {
box.addEventListener("dragover",function (e) {
console.log('elemenet dragover');
box.classList.add('over');
e.preventDefault();
});
box.addEventListener("dragleave", function (e) {
console.log('elemenet dragleave');
box.classList.remove('over');
e.preventDefault();
});
box.addEventListener("drop", function (e) {
e.preventDefault(); //取消浏览器默认拖拽效果
var fileList = e.dataTransfer.files; //获取拖拽中的文件对象
var len=fileList.length;//用来获取文件的长度(其实是获得文件数量)
//检测是否是拖拽文件到页面的操作
if (!len) {
box.classList.remove('over');
return;
}
box.classList.add('over');
window.willUploadFileList=fileList;
}, false);
}
openDropEvent();
function submitUpload() {
var fileList = window.willUploadFileList||[];
if(!fileList.length){
alert('请选择文件');
return;
}
var fd = new FormData(); //构造FormData对象
for(var i =0;i<fileList.length;i++){
fd.append('f1', fileList[i]);//支持多文件上传
}
var xhr = new XMLHttpRequest(); //创建对象
xhr.open('POST', 'http://localhost:8100/', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var obj = JSON.parse(xhr.responseText); //返回值
if(obj.fileUrl.length){
alert('上传成功');
}
}
}
xhr.send(fd);//发送
}
//绑定提交事件
document.getElementById('btn-submit').addEventListener('click',submitUpload);
</script>
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo/demo7
掘金的写文编辑器是支持粘贴上传图片的,比如我从磁盘粘贴或者从网页上右键复制图片。
DEMO
说明
div.editor-box
,开启contenteditable
div.editor-box
绑定paste
事件paste
事件,从event.clipboardData || window.clipboardData
获得数据items[i].getAsFile()
insertNodeToEditor
方法测试中发现复制多个文件无效,只有最后一个文件上传,在掘金的编辑器里也同样存在,在坐有知道原因的可以留言说下。
mac
系统可以支持从磁盘复制文件后上传,windows
系统测试未通过,剪贴板的数据未拿到。
HTML
<div class="editor-box" id="editor-box" contenteditable="true" >
可以直接粘贴图片到这里直接上传
</div>
JS
//光标处插入 dom 节点
function insertNodeToEditor(editor,ele) {
//插入dom 节点
var range;//记录光标位置对象
var node = window.getSelection().anchorNode;
// 这里判断是做是否有光标判断,因为弹出框默认是没有的
if (node != null) {
range = window.getSelection().getRangeAt(0);// 获取光标起始位置
range.insertNode(ele);// 在光标位置插入该对象
} else {
editor.append(ele);
}
}
var box = document.getElementById('editor-box');
//绑定paste事件
box.addEventListener('paste',function (event) {
var data = (event.clipboardData || window.clipboardData);
var items = data.items;
var fileList = [];//存储文件数据
if (items && items.length) {
// 检索剪切板items
for (var i = 0; i < items.length; i++) {
console.log(items[i].getAsFile());
fileList.push(items[i].getAsFile());
}
}
window.willUploadFileList = fileList;
event.preventDefault();//阻止默认行为
submitUpload();
});
function submitUpload() {
var fileList = window.willUploadFileList||[];
var fd = new FormData(); //构造FormData对象
for(var i =0;i<fileList.length;i++){
fd.append('f1', fileList[i]);//支持多文件上传
}
var xhr = new XMLHttpRequest(); //创建对象
xhr.open('POST', 'http://localhost:8100/', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
var obj = JSON.parse(xhr.responseText); //返回值
console.log(obj);
if(obj.fileUrl.length){
var img = document.createElement('img');
img.src= obj.fileUrl[0];
img.style.width='100px';
insertNodeToEditor(box,img);
// alert('上传成功');
}
}
}
xhr.send(fd);//发送
}
CODE
https://github.com/Bigerfe/fe-learn-code/blob/master/src/upfiles-demo/demo8/