express拖拽文件上传,XMLHttpRequest(),服务器端处理详解

本文详细介绍了如何利用HTML5的拖拽事件实现文件上传,并通过JavaScript处理客户端的FormData对象。同时,阐述了服务器端如何使用Express处理上传文件,包括设置文件大小限制及两种上传方法:使用FormData上传与直接上传文件对象。最后提供了服务器端处理上传文件的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  首先我的demo页面布局很简单:

<html>
<head>
    <title>XMLHttpRequest</title>
    <link href="/stylesheets/style.css" rel="stylesheet" type="text/css">
    <script src="/javascripts/jquery-1.7.2.js" type="text/javascript"></script>
    <script src="/javascripts/function.js" type="text/javascript"></script>
</head>
<body onload="upload()">
<div id="dropBox" class="droperea"  >
    <ul id="list"></ul>
    <p style="font-size: large;margin-left: 350px;padding-top:110px;" id="txterea">请将文件拖拽到这里上传</p>
</div>
</body>
</html>


1、client使用FormData对象上传或者直接上传文件对象
有关html5拖拽事件:
  • dragstart:要被拖拽的元素开始拖拽时触发,这个事件对象是被拖拽元素
  • dragenter:拖拽元素进入目标元素时触发,这个事件对象是目标元素
  • dragover:拖拽某元素在目标元素上移动时触发,这个事件对象是目标元素
  • dragleave:拖拽某元素离开目标元素时触发,这个事件对象是目标元素
  • dragend:在drop之后触发,就是拖拽完毕时触发,这个事件对象是被拖拽元素
  • drop:将被拖拽元素放在目标元素内时触发,这个事件对象是目标元素
  • 完成一次成功页面内元素拖拽的行为事件过程应该是: dragstart –> dragenter–> dragover –> drop –>dragend
  • //function.js
    function upload(){
        var droperea =document.getElementById("dropBox");
        var list=document.getElementById("list");
        var txterea=document.getElementById("txterea");
        //添加拖拽事件的监听
        droperea.addEventListener("dragenter",function(e){
            e.preventDefault();                           //阻止浏览器的默认行为
            droperea.style.backgroundColor = "grey";
        },false);
        droperea.addEventListener("dragleave",function(e){
            e.preventDefault();
            droperea.style.backgroundColor = "white";
        },false);
        droperea.addEventListener('drop', function(e){
            e.stopPropagation();
            e.preventDefault();
            droperea.style.backgroundColor = "white";
            var fileList =e.dataTransfer.files,//获取拖拽文件
                fileType = fileList[0].type,
                fileName = fileList[0].name,
                fileSize = fileList[0].size,
                div =document.createElement('div'),
                reader = new FileReader();
    //注意:只有在需要在页面展示图片的时候才需要使用FileReader()这个对象,
    //这个对象对文件的大小有限制,大概在500MB左右,否则会导致页面崩溃;
    
    //如果只是上传一个文件而不需要展示图片的话不需要使用这个对象
    
    //      reader.readAsDataURL(fileList[0]);//这里只取拖拽的第一个,实际中你可以遍历处理file列表
    //      reader.onload = function(e) {
            div.src=this.result;
            var formData = new FormData();
            var xhr = new XMLHttpRequest();
            //因为直接上传文件对象的时候我无法获取文件的信息所以我只能把文件的信息通过param传递过去
            var url ="/upload?fileName=" +fileName+'&fileSize='+fileSize;
            console.log(fileList[0]);
            formData.append("uploadFile",fileList[0]);
            xhr.open('POST',url, true);
            xhr.onload = function(e) {};
            // Listen to the uploadprogress.
            var progressBar =document.querySelector('progress');
            xhr.upload.onprogress = function(e) {
                if(e.lengthComputable) {
                    var percentComplete =parseInt((e.loaded / e.total) * 100);
                    console.log("Upload: " +percentComplete + "% complete");
                    div.innerHTML="name :  "+fileName+'     ' +percentComplete + "%";
                }
            };
    //          xhr.send(formData); //使用multipart/form-data格式上传
            xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");//直接发送文件对象的时候使用
            xhr.setRequestHeader("X-File-Name",encodeURIComponent(fileName));
            xhr.setRequestHeader("Content-Type","application/octet-stream");
            xhr.send(fileList[0]);//直接上传文件对象,
    //          xhr.abort();//表示取消文件上传
            list.a(div);//复制代码的时候把.a改成
    
            txterea.style.display="none";
    //      };
            reader.onabort=function(e){ //取消文件上传时触发
                alert('File readcancelled');
            };
    //其他的一些事件reader.onerror,reader.onloadstart,
    //reader.readAsBinaryString(e.target.files[0]);
        },false);
        droperea.addEventListener('dragover',function(e) {
            e.stopPropagation();
            e.preventDefault();
        },false);
    
    }
    function abortRead() {
        reader.abort(); // 取消浏览器读取本地文件
    }

 更多关于 FormDate

2、server处理上传的文件:
在服务器端使用express处理的时候要主要一个问题,它对req.headers[content-length]有大小的限制,如果我们使用默认设定的话只有20mb。一旦超出20mb就会报错:
  Error: Request Entity TooLarge
所以如果文件较大我们需要自己设定它:可以在varapp = express();下面加一句
app.use(express.limit('800mb'));不可以写在 app.configure里面这是我试验出来的暂时还没找到原因。

(1)处理使用formdata上传的数据;
    使用formdata上传文件的时候和处理普通的表单上传是一样的:req.files可以获得文件的基本信息,req.headers获取http请求的一些信息。因为这种方式是把文件暂存在缓存里的所以不适合上传大文件。




 

exports.upload=function(req,res){
    console.log(req.headers);
    console.log(req.files);
    var tmp_path = req.files.uploadFile.path; // 获得文件的临时路径
    var target_path = './public/upload/' +req.files.uploadFile.name;// 指定文件上传后的目录
    fs.rename(tmp_path, target_path, function(err) { // 移动文件
        if (err) throw err;
        fs.unlink(tmp_path, function() {// 删除临时文件夹文件,
            if (err) throw err;
            res.end();
        });
    });
};

(2)处理使用直接上传文件对象方法上传的数据:

   直接上传文件对象的时候req中包含的只是文件的数据所以我使用createWriteStream保存文件,这种方式适合上传大文件因为它不是暂存在缓存里的。 

var projectPath=__dirname.substring(0,__dirname.indexOf("/routes"));//取得项目的路径
exports.upload =function(req, res,next) {
    var fileName=req.param('fileName');//获取param中文件的信息
    var fileSize=req.param('fileSize');
    var target_path =projectPath+'/public/upload/' + fileName ;
    var wOption = {flags: 'w',encoding: null,mode: 0777};
    var fileStream = fs.createWriteStream(target_path,wOption);
    req.pipe(fileStream, { end: false });
    req.on('end', function() {
        console.log("传输完毕!");
        var transfer;
        fs.stat(target_path, function (err, data) {
            if (err) throw err;
            transfer=String(data.size);
            console.log("tmp file's size :",data.size);
            console.log("the received size is :",fileSize);
            if(transfer==String(fileSize)){
                res.send({success:true});
            }else{
                res.send({error:"文件在传输的过程中有丢失,传输失败!"});
            }
        });
    });
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值