您的位置:首页 > Web前端 > JQuery

多文件拖拽上传以及利用Jquery替代HTML5上传控件

2017-03-06 16:27 417 查看
最近一直在研究文件上传的各种方法以及使用其他控件去重构HTML5自带的上传控件,这一篇将会总结这段时间研究的文件上传的两种方式,并对这一方面告一段落。

本文将分为两部分介绍并解释文件上传的原理和实现过程,第一篇为多文件拖拽上传,类似于QQ邮箱文件拖拽一样;第二篇为使用Jquery代替HTML5上传控件,比较华丽的为每一个文件显示进度条和显示返回结果。

第一篇——拖拽

文件拖拽即把一个或多个文件从电脑桌面选中,拖移至我们的页面上传区,并记录下每一个文件的信息,反馈给后台。

首先是给出一个前台页面,一个form表单,包含它的各种属性,特别是(enctype=”multipart/form-data”) 这个属性是设置表单的MIME编码。默认情况,这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,form里面的input的值以2进制的方式传到后台,保留完整的传递文件数据,进行后台文件处理的操作.

<form id="upload" action="Handler1.ashx" method="post" enctype="multipart/form-data">
<div class="example ">
<div id="drop_zone">将文件拖拽到这里</div>
<div id="output_area"></div>
<input type="button" value="拖拽上传" onclick="Upload();" />
</div>
</form>


接下来会逐步展示并一步步解释完整的JS代码,请准备好瓜子和饮料:

初始化的四个基本参数,不得不说一下强大的FormData,它是XMLHttpRequest里面的一个接口,我们利用FormData对象,可以把所有表单元素的name与value组成一个queryString,提交到后台。之后使用XMLHttpRequest的 send( ) 方法来异步提交表单,与普通的ajax相比,使用FormData的最大优点就是可以异步上传二进制文件。

var fd = new FormData();
var FileIndex = 0;
var output = document.getElementById('output_area');
var dropZone = document.getElementById('drop_zone');


接下来我们就需要构造文件拖拽的过程:1.文件进入,2.文件离开,3. 文件拖拽完成效果,4.文件拖拽到页面后处理方式。









//首先对页面事件做一个判断处理,如果页面中存在并满足下列if条件就触发事件方法。
if ((('draggable' in dropZone) && ('ondragenter' in dropZone)
&& ('ondragleave' in dropZone) && ('ondragover' in dropZone)
&& window.File && window.FileList && window.FileReader)) {

//文件进入事件
function handleFileDragEnter(e) {
//不再派发事件
e.stopPropagation();
//取消事件的默认动作
e.preventDefault();
//为当前元素添加CSS样式(这里使用到的样式均会在下面展示出来)
this.classList.add('hovering');
}

//文件离开事件
function handleFileDragLeave(e) {
e.stopPropagation();
e.preventDefault();
//为当前元素移除CSS样式
this.classList.remove('hovering');
}

//文件拖拽完成效果
function handleFileDragOver(e) {
e.stopPropagation();
e.preventDefault();
//把拖动的元素复制到放置目标(注1会给出dropEffect详细属性)。
e.dataTransfer.dropEffect = 'copy';
}

//文件拖拽到页面后处理方式
function handleFileDrop(e) {
e.stopPropagation();
e.preventDefault();
//为当前元素移除CSS样式
this.classList.remove('hovering');

//target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
var files = e.target.files || e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
FileIndex++;
//FormData提供的append方法把数据写入到fd中
fd.append("FileData_" + FileIndex, files[i]);
}

var files = e.dataTransfer.files;
//根据files[]获得的数据,在前台页面写出上传的文件基本信息
var outputStr = [];
for (var i = 0, f; f = files[i]; i++) {
var lastModified = f.lastModifiedDate;
var lastModifiedStr = lastModified ? lastModified.toLocaleDateString() + ' ' + lastModified.toLocaleTimeString()
: 'n/a';
outputStr += '<li><strong>' + f.name + '</strong></li>';
}
output.innerHTML = '<ul>' + outputStr + '</ul>';
}

//为四种方法生成addEventListener事件监听器,addEventListener有三个参数:第一个参数表示事件名称;第二个参数表示要接收事件处理的函数;第三个参数为 useCapture(一般来说为false,true会更改响应顺序),
dropZone.addEventListener('dragenter', handleFileDragEnter, false);
dropZone.addEventListener('dragleave', handleFileDragLeave, false);
dropZone.addEventListener('dragover', handleFileDragOver, false);
dropZone.addEventListener('drop', handleFileDrop, false);
}


文件响应事件之后,就要为数据传递到后台做准备了:

function Upload() {
//创建XMLHttpRequest方法
var xhr = new XMLHttpRequest();
//添加事件监听器(同dropZone监听方法)
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false
e4bd
);
//使用open()和send()建立并发送响应事件
xhr.open("POST", "Handler1.ashx");
xhr.send(fd);
}

//显示进度条
function uploadProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').style.width = percentComplete + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}

//抛出反馈成功结果
function uploadComplete(evt) {
alert(evt.target.responseText);
}
//抛出异常提示
function uploadFailed(evt) {
alert("上传文件异常.");
}
//抛出取消提示
function uploadCanceled(evt) {
alert("取消.");
}


后台程序:接受前台数据并作出处理

if (context.Request.Files != null)
{
//服务器端文件保存路径
string uploadPath = HttpContext.Current.Server.MapPath(@context.Request["folder"]) + "\\file\\";
//循环对每一个文件作出处理
foreach (string fileDate in context.Request.Files.AllKeys)
{
HttpPostedFile f = context.Request.Files[fileDate];
if (f != null && f.FileName != "")
{
string title = context.Request.Form["title"];
f.SaveAs(uploadPath + f.FileName);//保存文件
context.Response.Write("上传成功");
}
}
}


第二篇——控件

这一篇将会使用Jquery替代HTML5的上传控件,并增加文件信息展示和上传进度条。

首先我们需要下载JqueryUploadify这一个控件包(注2提供下载链接地址),里面包含以下几个引用:

<script src="/js/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="/js/jquery.uploadify.v2.1.0.js" type="text/javascript"></script>
<script src="/js/jquery.uploadify.v2.1.0.min.js" type="text/javascript"></script>
<script src="/js/swfobject.js" type="text/javascript"></script>
<link href="/css/uploadify.css" rel="stylesheet" type="text/css" />


在前台页面中写入form表单和相应的按钮

<form id="form1" runat="server">
<div id="fileQueue">
</div>
<div>
<p>
<input type="file" name="uploadify" id="uploadify"/>
<input id="Button1" type="button" value="上传" onclick="javascript: $('#uploadify').uploadifyUpload()" />
<input id="Button2" type="button" value="取消" onclick="javascript: $('#uploadify').uploadifyClearQueue()" />
</p>
</div>
</form>


然后写一下uploadify的JS:

<script type="text/javascript">
$(document).ready(function () {

$("#uploadify").uploadify({
'uploader': 'image/uploadify.swf',  //uploadify.swf文件的相对路径,该swf文件是一个带有文字BROWSE的按钮,点击后淡出打开文件对话框
'script': 'Handler1.ashx',//    script :  后台处理程序的相对路径
'cancelImg': 'image/cancel.png',
'buttenText': '请选择文件',//浏览按钮的文本,默认值:BROWSE。
'sizeLimit':999999999,//文件大小显示
'floder': 'Uploader',//上传文件存放的目录
'queueID': 'fileQueue',//文件队列的ID,该ID与存放文件队列的div的ID一致
'queueSizeLimit': 120,//上传文件个数限制
'progressData': 'speed',//上传速度显示
'auto': false,//是否自动上传
'multi': true,//是否多文件上传
//'onSelect': function (e, queueId, fileObj) {
//    alert("唯一标识:" + queueId + "\r\n" +
//  "文件名:" + fileObj.name + "\r\n" +
//  "文件大小:" + fileObj.size + "\r\n" +
//  "创建时间:" + fileObj.creationDate + "\r\n" +
//  "最后修改时间:" + fileObj.modificationDate + "\r\n" +
//  "文件类型:" + fileObj.type);

//    },
'onQueueComplete': function (queueData) {
alert("文件上传成功!");
return;
}

});
});
</script>


最后后台程序和我们第一篇使用的后台处理是同一程序,下面是图片展示区:







如果报错或者超出文件上传限制将会用下面的方式提示用户



CSS样式区:

<style>
#drop_zone {
border: 2px dashed #BBB;
padding: 25px 5px;
text-align: center;
font-size: 20pt;
color: #BBB;
border-radius: 5px;
}
#drop_zone.hovering {
-webkit-box-shadow: inset 0px 0px 50px #BBB;
-moz-box-shadow: inset 0px 0px 50px #BBB;
-o-box-shadow: inset 0px 0px 50px #BBB;
box-shadow: inset 0px 0px 50px #BBB;
}
.example {
margin: 40px 25px;
padding: 10px;
border: 1px solid #BBB;
}
#description:first-line {
margin-left: 42px;
}
#output_area {
text-align: left;
}
#output_area li {
margin: 10px 0;
}
</style>


注1:运用dataTransfer对象,不仅仅能传输数据,还能通过dataTransfer对象确定被拖拽的元素以及作为放置目标的元素能够接收什么操作。

其中,通过dropEffect属性可以知道被拖动的元素能够执行哪种行为。这个属性的四个值如下:

none:不能把拖动的元素放在这里。这是除了文本框之外所有元素默认的值。

move:把拖动的元素移动到放置目标。

copy:把拖动的元素复制到放置目标。

link:放置目标会打开拖动的元素(但拖动的元素必须是个链接,有URL地址)。

把元素拖动到放置目标上的时候,以上每一个值都会导致光标显示为不同的符号。

注2:http://www.uploadify.com/documentation/ 官方控件包下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jquery html5 控件