HTML5托拽上传(XMLHttpRequest和Google Gears)

      HTML5的拖拽上传功能可拆分为两个部分实现,一个是对象的拖拽功能,另一个是上传功能。拖拽功能的实现基于HTML5 DOM对象的拖拽事件 ,FF3.6+和Chrome7+都实现了该功能,所以不用做特别的兼容,代码如下:

 
复制代码
拖拽功能代码
    var uploadZone=$("uploadZone"),
        iptFile,
        file,
        ffUpload
=new FirefoxFileUpload("http://localhost/upload/a.php"); 
        
//chromeUpload=new ChromeFileUpload("http://localhost/upload/a.php");
        
    
function focus(state){
        uploadZone.style.backgroundColor
=state?"#f0ab0c":"";
    }



    uploadZone.addEventListener(
"dragenter",function(e){
        focus(
true);
        e.stopPropagation();
        e.preventDefault();
    },
false);

    uploadZone.addEventListener(
"dragleave",function(e){
        focus(
false);

    },
false);

    uploadZone.addEventListener(
"dragover",function(e){
        e.stopPropagation();
        e.preventDefault();
    },
false);

    uploadZone.addEventListener(
"drop",function(e){
        e.stopPropagation();
        e.preventDefault();
        focus(
false);
        
        
//Firefox上传
        ffUpload.xhr.upload.onprogress=function(e){
            
var w=$("pgBorder").offsetWidth;
            
            $(
"progress").style.width=e.loaded/e.total*w+"px";
        };
        ffUpload.xhr.upload.onload
=function(){
            $(
"progress").style.width=$("pgBorder").offsetWidth+"px";
        };
        ffUpload.upload(ffUpload.getFile(e));

        
        
//Chrome上传
    //    chromeUpload.xhr.upload.onprogress=function(e){
    //        console.log(e.loaded/e.total*100+"%");
    //    };
    //    chromeUpload.upload(chromeUpload.getFile(e));
        
    },
false);
复制代码

而HTML5的文件传输功能则是基于两套实现方式:
    firefox:
        fileReader.readAsBinaryString 读取二进制串
        XMLHttpRequest.sendAsBinary 以二进制的格式发送给服务器端(真给力)
    
    chrome:
        gears API

因为XMLHttpRequest.sendAsBinary目前还没有被w3c列为标准,所以只能在Firefox中私有地使用。

以下是简单封装的两个浏览器的上传类
      
复制代码
Firefox 上传类
 var FirefoxFileUpload=function(url,dataName){
                
this.xhr=new XMLHttpRequest();
                
                
this.__file=null;
                
this.__fileReader=new FileReader();
                
this.__url=url;
                
this.__dataName=dataName || "FileData";
                
                
this.__initReader();
            };
            FirefoxFileUpload.prototype
={
                upload:
function(file){
                    
if(!file){
                        
return;
                    }
                    
                    
this.__file=file;
                    
this.__fileReader.readAsBinaryString(this.__file);
                },
                
                getFile:
function(e){
                    
return e.dataTransfer.files[0];
                },
                
                __send:
function(){
                    
var xhr=this.xhr,
                        boundary
="----------BOUNDARY"+(new Date()).getTime(),
                        body
=this.__getBody(this.__fileReader.result,boundary);
                    
                    xhr.open(
"post",this.__url,true);
                    xhr.setRequestHeader(
"Content-Type","multipart/form-data, boundary="+boundary);
                    xhr.setRequestHeader(
"Content-Length",this.__file.size);

                    xhr.sendAsBinary(body);
                },
                
                __initReader:
function(){
                    
var me=this;
                    
this.__fileReader.addEventListener("load",function(){
                        me.__send();
                    },
false);
                },
                
                __getBody:
function(readerResult,boundary){
                    
return ['--',boundary,'\r\n',
                            
'content-disposition: form-data; name="',this.__dataName,'"; filename="',encodeURI(this.__file.name),'"\r\n',
                            
'Content-Type: ',this.__file.type,'\r\n\r\n',
                             readerResult,
"\r\n",
                            
'--',boundary,'--\r\n'
                        ].join(
"");
                }
                
            };
复制代码

复制代码
Chrome 上传类
var ChromeFileUpload=function(url,dataName){
                
this.xhr=google.gears.factory.create("beta.httprequest");
                
                
this.__url=url;
                
this.__file=null;
                
this.__builder=google.gears.factory.create("beta.blobbuilder");
                
this.__dataName=dataName || "FileData";
            };
            ChromeFileUpload.prototype
={
                upload:
function(file){
                    
this.__file=file;
                    
this.__send();
                },
                
                getFile:
function(e){
                    
var desktop=google.gears.factory.create("beta.desktop");
                    
return desktop.getDragData(e,"application/x-gears-files").files[0];
                },
                
                __send:
function(){
                    
var xhr=this.xhr,
                        boundary
="----------BOUNDARY"+(new Date()).getTime();
                    
                    xhr.open(
"post",this.__url,true);
                    xhr.setRequestHeader(
"Content-Type","multipart/form-data, boundary="+boundary);
                    
                    
this.__updateBuilder(boundary);
                    xhr.send(
this.__builder.getAsBlob());
                },
                
                __updateBuilder:
function(boundary){
                    
var bdr=this.__builder;
                    
                    bdr.append([
'--',boundary,'\r\n',
                                
'content-disposition: form-data; name="',this.__dataName,'"; filename="',encodeURI(this.__file.name),'"\r\n',
                                
'Content-Type: ',this.__file.type,'\r\n\r\n'].join(""));
                    bdr.append(
this.__file.blob);
                    bdr.append([
"\r\n",
                                
'--',boundary,'--\r\n'
                                ].join(
""));
                }
            };
复制代码

两种上传方式都是用的基于表单的文件传输协议 RFC-1867  (RFC-1867 中文版)。

这两个类配合前面的拖拽代码即可实现HTML5版的拖拽上传。。。。。有了标准才是真的方便啊。。。。

posted @   随机  阅读(2601)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
历史上的今天:
2010-02-28 程序员要多喝水
点击右上角即可分享
微信分享提示