原生API实现拖拽上传文件实践
功能:
拖拽上传文件、图片,上传的进度条,能够同时上传多个文件。
完整的demo地址:https://github.com/qcer/FE-Components/tree/master/QDrag
涉及到的API:
1、HTML5的拖拽事件:dragenter,dragover,drop等
2、XMLHttpRequest Level2
3、FormData
4、(扩展:HTML5的File API)
概述:
1、利用拖拽实践的API将一个普通的div自定义成一个放置目标,这里有一个技巧是放置一个隐藏的input[type='file']的元素,在div上绑定input的点击事件,再点击事件中触发input的click事件,能够在div上任意位置达到type=file选择文件上传的效果。
2、在div的drag事件中获取文件对象,通过FormData对象构造表单序列化的数据,同时动态生成页面元素,通过XMLHttpRequest对象发送数据,在xhr.upload的progress事件中实现上传进度的功能。
3、后端通过nodejs实现一个http服务器,接受数据,进而可以扩展的解析数据。
前端页面代码:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#qdrag{
height: 300px;
width: 100%;
background: #eee;
border-radius: 5px;
padding-top: 20px;
}
#qdrag-hidden {
display: none;
position: absolute;
z-index: 10;
}
#qdrag .qdragzone{
width: 100%;
height: 50px;
background: #ccc;
line-height: 50px;
border-bottom: 2px solid #fff;
border-radius: 2px;
overflow: hidden;
} #qdrag .qdragzone img{
margin-top: 9px;
margin-left: 2%;
margin-right: 4%;
float: left;
}
#qdrag .qdragzone span{
display: inline-block;
font-weight: bold;
font-size: 14px;
float: left;
width: 20%;
color: #339966;
font-family: "Times New Roman", Times, serif;
/*font-family:Arial,Helvetica,sans-serif;font-size:100%;*/
}
#qdrag .qdragzone progress{
border-radius: 6px;
height: 12px;
width: 250px;
color: #5cb85c;
background:#fff;
}
progress::-moz-progress-bar { background: #fff;border-radius: 6px; }
progress::-webkit-progress-bar { background: #fff;border-radius: 6px;} progress::-webkit-progress-value {background-color:#5cb85c;border-radius: 6px;}
progress::-moz-progress-value { background-color:#5cb85c;border-radius: 6px;}
}
</style>
</head>
<body> <div id="qdrag">
<input type="file" id="qdrag-hidden" name="image" value=""></input>
<div class="qdragzone">
<img src="./public/upload.png">
<span>Name:test.txt</span>
<span>Size:00000 Byte</span>
<progress value="0.2" max="1">
</div>
</div>
<script type="text/javascript">
var qdrag = document.getElementById('qdrag');
var qdrag_hidden = document.getElementById('qdrag-hidden');
qdrag.onclick = function () { qdrag_hidden.click();}
qdrag_hidden.onchange = function () {
// body...
var fileList = this.files;
for (var i = 0; i < fileList.length; i++) {
sendFileByXHR('./upload.html',fileList[i]);
}
} function sendFileByXHR(url,fielObj) {
// body...
var xhr = new XMLHttpRequest();
var newprogress = createTagsEle(fielObj).newprogress;
xhr.upload.onprogress = function (event) {
// body...
console.log('xhr-loaded:'+event.loaded);
newprogress.setAttribute('value',event.loaded/event.total);
}
xhr.onreadystatechange = function () {
// body...
if (xhr.status === 200 && xhr.readyState === 4) {
console.log(xhr.responseText);
}
}
xhr.onabort = function (event) {
// body...
console.log('abort');
}
xhr.onerror = function (event) {
// body...
console.log('error');
}
var data = new FormData();
data.append(fielObj.name,fielObj);
xhr.open('POST',url,true);
xhr.send(data); }
function createTagsEle(fileObj) {
// body...
//create
var fragment = document.createDocumentFragment();
var newdiv = document.createElement('div');
var newimg = document.createElement('img');
var newspanName = document.createElement('span');
var newspanSize = document.createElement('span');
var newprogress = document.createElement('progress'); //set attribute
newdiv.setAttribute('class','qdragzone');
newimg.setAttribute('src','./public/upload.png')
newspanName.innerHTML = 'Name: ' + fileObj.name;
newspanSize.innerHTML = 'Size: ' + fileObj.size+' Byte';
newprogress.setAttribute('value',0);
newprogress.setAttribute('max',1); //append
fragment.appendChild(newdiv);
newdiv.appendChild(newimg);
newdiv.appendChild(newspanName);
newdiv.appendChild(newspanSize);
newdiv.appendChild(newprogress); // append to DOM
qdrag.appendChild(fragment);
return {newprogress};
} qdrag.addEventListener('dragover',function (event) {
// body...
event.preventDefault();
});
qdrag.addEventListener('dragenter',function (event) {
// body...
event.preventDefault();
});
qdrag.addEventListener('drop',function (event) {
// body...
event.preventDefault();
var fileList = Array.from(event.dataTransfer.files);
for (var i = 0; i < fileList.length; i++) {
sendFileByXHR('./upload.html',fileList[i]);
}
}); </script>
</body>
</html>
后端代码:
var http = require('http');
var fs = require('fs')
const PORT = 44444;
const MIME = {
default:'text/plain',
html:'text/html',
css:'text/css',
js:'text/javascript',
png:'image/png',
jpg:'image/jpg',
jpeg:'image/jpeg',
json:'application/json',
from:'multipart/form-data'
}
function handleStaticResource(req,res) {
// body...
var param = req.url.replace('/public','');
var staticResource = fs.readFileSync('.'+param,'utf8');
var fileType = req.url.split('/').pop().split('.').pop();
switch(true){
case ['js','css'].includes(fileType):
res.setHeader('Content-Type',MIME[fileType]);
break;
case ['png','jpg','jpeg'].includes(fileType):
staticResource = new Buffer(fs.readFileSync('.'+param,'base64'),'base64');
console.log(fileType);
res.setHeader('Content-Type',MIME[fileType]);
break;
default :
res.setHeader('Content-Type',MIME['default']);
console.log(MIME['default']);
break;
}
res.end(staticResource);
}
var router = function (req,res) {
// body...
res.render = function (path,options) {
// body...
var content_html = fs.readFileSync(path,'utf8');
res.writeHead(200,{'Content-Type':MIME['html']});
res.end(new Buffer(content_html,'utf8'));
}
switch(true){
case /^\/public\/([\s\S]*)/.test(req.url):
handleStaticResource(req,res);
break;
case req.url === '/':
// console.log(req.url);
res.render('./testdrag.html');
break;
case req.url === '/upload.html':
// console.log(req.headers);
var buffers = [];
req.on('data',function (chunk) {
// body...
buffers.push(chunk);
})
req.on('end',function () {
// body...
var data = Buffer.concat(buffers).toString();
res.end("ok");//正确的调用位置
})
// res.end('currSize:' + buffers.length +' '+ (new Date()).toGMTString());//错误的调用位置
break;
default:
// console.log(req.url);
res.end();
};
}
var server = http.createServer(router);
server.listen(PORT,function () {
// body...
console.log(`the server is linstening on port ${PORT}`);
})
效果:

原生API实现拖拽上传文件实践的更多相关文章
- Thinkphp拖拽上传文件-使用webuploader插件(自己改动了一些地方)——分片上传
html页面: <!DOCTYPE html> <html class="js cssanimations"> <head> <meta ...
- Xshell拖拽上传文件插件
lrzsz是一款在linux里可代替ftp上传和下载的程序.在linux中支持直接拖拽上传的插件:同时也支持rz和sz进行命令上传和下载. 插件安装 yum -y install lrzsz 上传(r ...
- 实现拖拽上传文件的一款小控件——dropzone
由于专注所以专业.非常多小巧的东西乍一看非常不起眼,却在特定的领域表现不俗,就是由于集中了热情. dropzone就是这样一款小控件,实现拖拽上传.它不依赖于其他像jquery等JS库.并且支持多方面 ...
- day25—JavaScript实现文件拖拽上传案例实践
转行学开发,代码100天——2018-04-10 今天记录一个利用JavaScript实现文件拖拽上传到浏览器,后天将文件打开的小案例. 基本功能:1点击添加文件 2 文件拖拽添加 html: < ...
- js拖拽上传 文件上传之拖拽上传
由于项目需要上传文件到服务器,于是便在文件上传的基础上增加了拖拽上传.拖拽上传当然属于文件上传的一部分,只不过在文件上传的基础上增加了拖拽的界面,主要在于前台的交互, 从拖拽的文件中获取文件列表然后调 ...
- ajax拖拽上传文件
AJAX拖拽上传 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Linux拖拽上传文件 lrzsz
首先安装lrzsz 命令为:yum install lrzsz 安装完毕后直接将.tar.gz格式的文件拖如xshell的窗口内就会自动上传.
- html5 拖拽上传文件时,屏蔽浏览器默认打开文件
参考: https://www.cnblogs.com/kingsm/p/9849339.html
- input文件上传(上传单个文件/多选文件/文件夹、拖拽上传、分片上传)
//上传单个/多个文件 <input title="点击选择文件" id="h5Input1" multiple="" accept= ...
随机推荐
- group by 多字段分组
在平时的开发任务中我们经常会用到MYSQL的GROUP BY分组, 用来获取数据表中以分组字段为依据的统计数据.比如有一个学生选课表,表结构如下: Table: Subject_Selection S ...
- 自制ACL+DHCP实验(初版)
(实验用gns模拟器) ACL 实验拓扑: 实验要求: 1.1.1.1→3.3.3.3 不通 11.11.11.11→3.3.3.3 通 2.2.2.2→3.3.3.3 通 实验步骤: 步骤一:基本配 ...
- JQuery中的表单验证及相关的内容
前 言 JRedu Android应用开发中,经常要用到表单.既然用到了表单,那就不可避免的要用到表单的验证.但是,在提交表单时,但是,并不是,每次提交的表单内容都是正确的,如果 每次都将表单的 ...
- 个人作业(3)----个人总结(Alpha阶段)
一.个人总结. 个人完成的任务:在此阶段我完成了用户调研.部分测试以及部分博客书写. 个人及团队心得:经过几周Alpha阶段开发后,我大致了解了开发软件的过程,开发一个软件并没有以往想象中那么简易,在 ...
- 团队作业4——第一次项目冲刺(Alpha版本)2017.4.26
2017.04.26 天气热. 时间:上午 9:35 ---10:10分 地点:陆大304实验室 会议内容:今天将昨天的的一些问题进行了讨论,以及针对助教提出的问题进行了分析,是因为我们昨天经过讨论后 ...
- 201521123061 《Java程序设计》第三周学习总结
1. 本章学习总结 2. 书面作业 **Q1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2 ...
- 201521123033《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. answer: 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号 ...
- 201521123079《java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...
- ecshop商城系统登录出现登录闪退问题
症状:ecshop商城系统提示登录成功,而且状态也是登录,一刷新,自动退出了,真坑爹 解决方案: 1.点着点着经常无故退出,感觉session被清空了.查找原因:ecshop中有用ip地址来验证,而公 ...
- JSP第二篇【内置对象的介绍、4种属性范围、应用场景】
什么是JSP内置对象 JSP引擎在调用JSP对应的jspServlet时,会传递或创建9个与web开发相关的对象供jspServlet使用.JSP技术的设计者为便于开发人员在编写JSP页面时获得这些w ...