高仿163网盘无刷新多文件上传系统文档格式.docx

上传人:b****5 文档编号:19623127 上传时间:2023-01-08 格式:DOCX 页数:15 大小:28.98KB
下载 相关 举报
高仿163网盘无刷新多文件上传系统文档格式.docx_第1页
第1页 / 共15页
高仿163网盘无刷新多文件上传系统文档格式.docx_第2页
第2页 / 共15页
高仿163网盘无刷新多文件上传系统文档格式.docx_第3页
第3页 / 共15页
高仿163网盘无刷新多文件上传系统文档格式.docx_第4页
第4页 / 共15页
高仿163网盘无刷新多文件上传系统文档格式.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

高仿163网盘无刷新多文件上传系统文档格式.docx

《高仿163网盘无刷新多文件上传系统文档格式.docx》由会员分享,可在线阅读,更多相关《高仿163网盘无刷新多文件上传系统文档格式.docx(15页珍藏版)》请在冰豆网上搜索。

高仿163网盘无刷新多文件上传系统文档格式.docx

其实原理跟一般用iframe实现无刷新提交表单是一样的,只是这里换成是文件。

这里关键就是把form的target设为iframe的name:

this.Form.target 

this._FrameName;

【iframe】

如果没有自定义iframe,程序在初始化时会自动创建无刷新所需的iframe的。

首先必须选择一个iframe名,这在无刷新时是必须的,为了每个实例能创建各自的iframe,这里用了一个随机数:

this._FrameName 

uploadFrame_"

Math.floor(Math.random() 

1000);

也可以用一个递增的计算器来代替随机数。

接着创建iframe,本以为用document.createElement("

iframe"

)创建再设置它的name属性就行了。

却发现这样设置的name在ie居然不认(有说name是只读属性),还好在网上找到一个方法:

“IE创建元素,还有一个特点,就是可以连同属性一同创建”。

例如我想给动态创建的iframe设置name,可以这样:

document.createElement("

<

iframe 

name=\"

\"

>

不过这个方式在ff会报错:

uncaughtexception:

Stringcontainsaninvalidcharacter(NS_ERROR_DOM_INVALID_CHARACTER_ERR)

估计是用createElement时不能带name,标准应该也是这样,所以兼容的方式这样写:

Code

var 

oFrame 

isIE 

?

) 

:

);

//为ff设置name

oFrame.name 

oFrame.style.display 

none"

关于这方面更详细的内容请看这里。

创建完还需要插入到body中,一般的做法是使用document.body.appendChild,但在ie中会有“已终止操作”错误,可以用下面这段代码测试:

body>

div>

script>

document.body.appendChild(document.createElement("

div"

));

/script>

/div>

/body>

网上找到一个解析:

“原来FF下的实现机制是当页面还没有完全读取完时body元素就已经存在了,而IE只有页面完全读取结束body元素才会存在,所以在页面中插入上面这条语句在IE下就会出现错误”。

我在web开发未解之谜中也提到了这个现象,我这里使用了insertBefore代替:

document.body.insertBefore(oFrame, 

document.body.childNodes[0]);

在服务器端文件传送完(或失败)之后,怎么通知客户端呢?

这里说说我的方法,首先我在客户端定义一个函数:

function 

Finish(msg){ 

alert(msg);

location.href 

location.href;

}

很简单,就是显示提示并重新加载页面(如果使用reload会导致ff中iframe重复加载数据)。

那服务器端如何通知客户端的问题,就是iframe如何跟主页面交互。

答案是通过window.parent或window.top,在iframe中parent和top属性“分别返回立即父窗口和最上层的祖先窗口”。

例如我在服务器端处理完数据之后会输出:

context.Response.Write("

window.parent.Finish('

_msg 

'

就会执行主页面的Finish函数了。

【多文件上传】

对于多文件上传,这里的目的是如何做到163网盘那样,只用一个file控件就实现多文件上传。

这里参考了163网盘的思路,下面说说如何实现:

首先必须有一个文件空间(我自己定的名字),例如程序中的"

idFile"

对象,这个空间不需要内容甚至一个div就可以,主要是用来存放file控件,程序中Folder属性就是这个文件空间对象。

ps:

这里的要求是把file控件都控制在文件空间里,即使不是单file控件的情况。

再说说Files属性,这个属性放的是file控件集合,方便获取file控件,在下面“文件列表”就会用到。

处理这些file控件的程序主要在Ini函数中:

首先是处理文件空间中的file控件:

this.Files 

[];

//整理文件空间,把有值的file放入文件集合

Each(this.Folder.getElementsByTagName("

input"

), 

Bind(this, 

function(o){

if(o.type 

== 

file"

){ 

o.value 

&

this.Files.push(o);

this.onIniFile(o);

}))

可以看到这里主要是把file控件放入到Files中,并执行附加函数onIniFile,我是这样定义这个函数的:

onIniFile:

function(file){ 

file.value 

file.style.display 

this.Folder.removeChild(file);

这里为了实现单file控件,把原来有值的file都隐藏了,还有那个“单file控件”呢?

别急,接着就在文件空间插入一个新的file控件:

file 

file.name 

this.FileName;

file.type 

file.onchange 

function(){ 

this.Check(file);

this.Ini();

});

this.Folder.appendChild(file);

可以看到file控件的name是FileName属性的值,默认是空的,如果服务器端需要这个name的话就可以设置。

这里可以看到每个file控件都有onchange来执行检测函数Check,这样每次选择文件后都会用Check检测一次,这里说说这个Check函数:

//检测变量

bCheck 

true;

//进行空值、文件数、后缀名、同值检测

if(!

file.value){

false;

this.onEmpty();

else 

if(this.Limit 

this.Files.length 

this.Limit){

this.onLimite();

!

this.ExtIn.length 

RegExp("

\.("

this.ExtIn.join("

|"

)$"

 

i"

).test(file.value)){

//检测是否允许后缀名

this.onNotExtIn();

this.ExtOut.length 

this.ExtOut.join("

).test(file.value)) 

{

//检测是否禁止后缀名

this.onExtOut();

this.Distinct) 

Each(this.Files, 

function(o){ 

if(o.value 

file.value){ 

})

bCheck){ 

this.onSame();

里面有一个检测变量bCheck,然后进行空值、文件数限制、后缀名、相同文件的检测,当其中一个步骤不通过bCheck就会设为false,一个常用的检测结构。

这里说说检测后缀名,由于js不能像后台那样获取文件的文件类型,所以只能根据后缀名来判断,例如用正则判断:

/\.(jpg|gif)$/i.test(file.value)

这样判断显然是不够的,所以如果要做文件类型判断的话一定要在后台用ContentType再判断一次。

最后如果没有通过检测就会执行onFail函数:

this.onFail(file);

我在onFail函数中设定了移除没有通过检测的file控件:

onFail:

这样就基本实现(正确的说是模拟)了单file控件上传多个文件的效果了。

【文件列表】

在上面的Ini函数中,最后执行了一个附加函数onIni,这个函数是用户自己定义的,我就在这个函数中添加文件列表。

在之前先说说添加文件列表的函数AddList,这个函数是用来把file控件的值列在一个table里面。

函数的参数是一个二维数组,其中第一维是行(tr),第二维是列(td)。

首先获取列表对象FileList,再定义一个文档碎片oFragment来操作dom:

FileList 

$("

idFileList"

oFragment 

document.createDocumentFragment();

然后用两个Each把二维数组插入到文档碎片中:

Each(rows, 

function(cells){

row 

tr"

Each(cells, 

cell 

td"

if(typeof 

string"

cell.innerHTML 

o;

}else{ 

cell.appendChild(o);

row.appendChild(cell);

oFragment.appendChild(row);

其中用了一个判断if(typeofo=="

),如果是文本就直接用innerHTML插入td,如果不是文本(这里不是文本就是一个对象)就用appendChild插入到td。

当数据都插入到文档碎片,就准备把文档碎片插入到FileList中,不过还有一个步骤就是清空FileList中原有的数据。

本来把innerHTML设为空来清空FileList会更有效率,但ie的table中只有td支持innerHTML,所以只好用removeChild来清空:

while(FileList.hasChildNodes()){ 

FileList.removeChild(FileList.firstChild);

之后就可以把文档碎片插入了:

FileList.appendChild(oFragment);

继续看onIni函数,现在只需要把要显示的数据组成一个二维数组,再用AddList就能显示文件列表了,这时存放file控件集合的Files属性就大有用处了。

首先定义一个放显示数据的数组:

arrRows 

然后根据Files对这个数组赋值:

if(this.Files.length){

oThis 

this;

a"

a.innerHTML 

取消"

a.href 

javascript:

void(0);

a.onclick 

oThis.Delete(o);

return 

};

arrRows.push([o.value, 

a]);

arrRows.push(["

font 

color='

gray'

没有添加文件<

/font>

nbsp;

]);

AddRow(arrRows);

当Files没有控件时只是输出“没有添加文件”,有控件时就会把每个file控件的要显示数据放到一个数组中,可以看到这个数组其实就是td内容的集合,接着把这个数组加入到arrRows中形成二维数组,最后把得到的arrRows给AddRow函数显示数据就行了。

为了能取消指定的file控件,这里插入了一个a来触发删除函数Delete,这里也有一个技巧,这里把href设为"

,并在onclick中返回false,这样能最大程度的实现仅仅执行js而不去跳转。

在表单提交时也要重新显示文件列表,表单提交后就不允许删除文件了,只显示文件路径就行了:

idBtnupload"

).onclick 

function(){

//显示文件列表

Each(fu.Files, 

AddList(arrRows);

fu.Folder.style.display 

idProcess"

).style.display 

idMsg"

).innerHTML 

正在添加文件到您的网盘中,请稍候……<

br 

/>

有可能因为网络问题,出现程序长时间无响应,请点击“<

href='

red'

取消<

/a>

”重新上传文件"

fu.Form.submit();

说到表单提交要注意一个问题,就是表单是不能嵌套的,最好是把表单放到服务器表单之外,没有办法才使用服务器表单作为提交表单(由于程序会修改提交表单的属性,所以尽量不要这样使用)。

这样文件列表就完成了,有兴趣的话也可以自己封装一下这个功能。

【file样式】

到此,程序的功能都已经实现了,但在163网盘中还有一个特别的地方,就是file控件的样式。

如果有用过163网盘上传文件,就知道那个file控件就像一个按钮,但功能确实是一个file控件。

但当自己尝试修改file控件的样式时,发现单单设置file控件的样式并不能实现想要的效果。

于是我想了另一个办法,用一个button来模拟,结果发现也不行,用js根本操作不了file控件,应该是考虑到安全问题吧。

最后是参考了163网盘和muxrwc模拟126附件添加的效果,总结了这个方法:

1.指定用一个容器(例如程序中的idFile)。

容器最好指定高和宽,并且overflow为hidden,不是块级元素的最好设display为block(为了高和宽的正确呈现);

2.在容器里放一个file控件,并设置样式,使能触发弹出选择文件框的部分覆盖整个容器,并设置成全透明。

容器指定准确的高和宽就是为了能通过file控件中不多的能设置的样式来覆盖整个容器;

3.现在已经把容器模拟成file控件了,可以直接设置容器的样式来模拟设置file控件的样式了。

在程序中主要用file控件的margin-left和font-size来实现覆盖整个容器:

a.files 

input 

margin-left:

-350px;

font-size:

30px;

cursor:

pointer;

filter:

alpha(opacity=0);

opacity:

0;

至于容器,我使用了有伪类hover的a元素(虽然CSS2中hover可以应用于任何对象,但ie6不支持)。

这里用了一个常用的小技巧,就是用一张图片作为背景通过在hover时修改background-position来实现两张图片的效果:

width:

90px;

height:

overflow:

hidden;

display:

block;

border:

1px 

solid 

#BEBEBE;

background:

url(img/fu_btn.gif) 

left 

top 

no-repeat;

text-decoration:

none;

a.files:

hover 

background-color:

#FFFFEE;

background-position:

-30px;

在点击这个a时后会出现一个虚线框,在这里显然不太美观,可以把outline设为none来去掉,可是ie又不支持,在网上找到一个方法ie可以把hideFocus设为true来隐藏聚焦(即不显示这个虚线框,hideFocus可以在js或html中设置,也可以通过expression放到css中:

a.files, 

outline:

/*ff* 

/

hide-focus:

expression(this.hideFocus=true);

/*ie* 

这样完全模拟了163网盘的效果了。

【后台】

前台基本完成了,就到后台啦。

后台的功能很简单,就是处理传递过来的文件数据。

这里像js+.Net图片切割系统那样使用ashx文件处理IHttpHandler发送过来的数据。

程序很简单,就直接贴代码了:

int 

iTotal 

context.Request.Files.Count;

if 

(iTotal 

0)

没有数据"

else

iCount 

for 

(int 

iTotal;

i++)

HttpPostedFile 

context.Request.Files[i];

(file.ContentLength 

|| 

string.IsNullOrEmpty(file.FileName))

//保存文件

file.SaveAs(System.Web.HttpContext.Current.Server.MapPath("

./file/"

Path.GetFileName(file.FileName)));

//这里可以根据实际设置其他限制

(++iCount 

UploadFileLimit)

超过上传限制:

UploadFileLimit;

break;

这里只检测了有无文件和文件数限制,其他检测如文件大小等可以自己扩展,应该不难。

处理完数据之后就通知客户端:

这个在上面iframe的内容中已经说明了。

使用说明

基本使用很简单,实例化一个file对象,其中参数分别是form对象,文件空间对象:

new 

FileUpload("

uploadForm"

这样就实现了一个简单的无刷新上传文件表单。

还可以使用这几个属性:

Form//表单

Folder//文件控件存放空间

Files//文件集合

更多的功能可以选择设置这些属性:

属性名:

默认值//说明

FileName:

//文件上传控件的name,配合后台使用

FrameName:

//iframe的name,要自定义iframe的话这里设置name

function(){},//整理文件时执行(其中参数是file对象)

onEmpty:

function(){},//文件空值时执行

Limit:

0,//文件数限制,0为不限制

onLimite:

fu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 远程网络教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1