HTML5的File API

说到File API,比如有意思就是图片上传了。国外有一个网站叫min.us  用户只需要把图片拖到网页面中,然后自己进行排序就OK了,很方便。

下面是关于它的一段介绍视频:

 

目前网页上传分为三种:

1、form提交

2、flash上传

3、插件上传

各有利弊,fomr提交就是没进度条,不太好取消。flash比较难搞的就是在非ie中浏览器认为flash是新窗口会话,当前网页的cookie无法传递到flash上传工具中,而针对这个一般就是用JS把当前页面中的cookie通过flash再传给后台,而对于一个后台如果使用了统一验证身份的接口那可能会有点麻烦。第三种优势很明显,比如适合如QQ空间这样用户需要大批量上传图片的,缺点也显而易见:跨浏览器上存在问题。而HTML5中的FileReader对象与as3中的很像,只不过目前as3中的方法比这个多(有兴趣可以自己去看看adobe的lives docs,对比一下两者的区别与共同点)。

 

讲了这么多,回到正题:File API,拿图片上传为例(FileFileReader):

1、首先,如何控制用户单选、多选。as3中是两个不同的对象:FileReference、FileReferenceList,在as3中可以使用FileFilter过滤只允许选择的上传文件。as3中需要使用flash player 10+才支持本地预览,而且图片不易过大。

HTML5中允许选择多个文件:

<input type="file" multiple>

只允许上传一个文件:

<input  type="file" single>

2、如何让用户只能上传指定的文件格式,如上传图片组件只允许png、jpg、gif、jpeg、bmp后缀格式的图片。

我尝试着去寻找HTML5中是否也如as3中可以让开发者自定义过滤选择文件呢,结果被我找到了http://en.wikipedia.org/wiki/File_select  添加一个属性就好了accept="image/gif,image/png"

image

默认为“自定义文件”,如果我选择“所有文件”,所有的文件都将显示出来。

image

image

3、上传文件

这里遇到一个问题,如何获取ajax发送过去的图片信息。因为在ajax中使用的是setRequestHeader将图片信息传给后台,因为使用的nginx,无法直接获取

自定义的http-header,就修改了fastcgi-params,加了三项:

image 
关于定义的配置规则,可以参考这一篇文章:nginx下php获取自定义请求头参数的方法

 

搜索了很多关于html5 upload的例子,有人用.net、ruby写了,但没有找到用php写的(有是有,不过是使用提交form至iframe的方法,不符合这里的需求),比如这个:http://valums.com/ajax-upload/   http://www.atwebresults.com/php_ajax_image_upload/

查了很久(已经很晚了,明天还得上班就不折腾了),暂时放弃php的部分,有空再写完整的例子,重点是看File、FileReader的方法(实现了本地预览的功能)

本地运行的效果:

image

 

有空再把完整的demo提供下载(暂时缺省后台php保存文件的方法),html的源码:

<!DOCTYPE html>
<html>
<head>
<title>File API</title>
<meta charset="utf-8">
<style>
#drop-area {
height: 50px;
line-height:50px;
text-align: center;
border: 2px dashed #ddd;
padding: 10px;
margin-bottom: 2em;
}

#drop-area .drop-instructions {
display: block;
height: 30px;
}

#drop-area .drop-over {
display: none;
font-size: 25px;
height: 30px;
}

#drop-area.over {
background: #ffffa2;
border: 2px dashed #000;
}

#drop-area.over .drop-instructions {
display: none;
}

#drop-area.over .drop-over {
display: block;
}

#drop-area.over .drop-over {
display: block;
font-size: 25px;
}


#file-list {
list-style: none;
margin-bottom: 3em;
}

#file-list li {
border-bottom: 1px solid #000;
margin-bottom: 0.5em;
padding-bottom: 0.5em;
}

#file-list li.no-items {
border-bottom: none;
}

#file-list div {
margin-bottom: 0.5em;
}

#file-list li img {
max-width: 400px;
}

#file-list .progress-bar-container {
width: 400px;
height: 10px;
border: 1px solid #555;
margin-bottom: 20px;
}

#file-list .progress-bar-container.uploaded {
height: auto;
border: none;
}

#file-list .progress-bar {
width: 0;
height: 10px;
font-weight: bold;
background: #6787e3;
}

#file-list .progress-bar-container.uploaded .progress-bar{
display: inline-block;
width: auto;
color: #6db508;
background: transparent;
}
</style>
</head>

<body>

<section id="main-content">
<h2>文件上传</h2>
<h3>请选择文件</h3>
<p>
<input id="files-upload" type="file" multiple accept="*.*" name="file">
</p>
<p id="drop-area">
<span class="drop-instructions">将文件拖拽到这里</span>
<span class="drop-over">Drop files here!</span>
</p>

<ul id="file-list">
<li class="no-items">&nbsp;</li>
</ul>
</section>

<script>
   1:  
   2:     !(function () {
   3:         var filesUpload = document.getElementById("files-upload"),
   4:             dropArea = document.getElementById("drop-area"),
   5:             fileList = document.getElementById("file-list");
   6:             
   7:         function uploadFile (file) {
   8:             var li = document.createElement("li"),
   9:                 div = document.createElement("div"),
  10:                 img,
  11:                 progressBarContainer = document.createElement("div"),
  12:                 progressBar = document.createElement("div"),
  13:                 reader,
  14:                 xhr,
  15:                 fileInfo;
  16:                 
  17:             li.appendChild(div);
  18:             
  19:             progressBarContainer.className = "progress-bar-container";
  20:             progressBar.className = "progress-bar";
  21:             progressBarContainer.appendChild(progressBar);
  22:             li.appendChild(progressBarContainer);
  23:             
  24:             /*
  25:                 If the file is an image and the web browser supports FileReader,
  26:                 present a preview in the file list
  27:             */
  28:             if (typeof FileReader !== "undefined" && (/image/i).test(file.type)) {
  29:                 img = document.createElement("img");
  30:                 li.appendChild(img);
  31:                 reader = new FileReader();
  32:                 reader.onload = (function (theImg) {
  33:                     return function (evt) {
  34:                         theImg.src = evt.target.result;
  35:                     };
  36:                 }(img));
  37:                 reader.readAsDataURL(file);
  38:             }
  39:             
  40:             // Uploading - for Firefox, Google Chrome and Safari
  41:             xhr = new XMLHttpRequest();
  42:             
  43:             // Update progress bar
  44:             xhr.upload.addEventListener("progress", function (evt) {
  45:                 if (evt.lengthComputable) {
  46:                     progressBar.style.width = (evt.loaded / evt.total) * 100 + "%";
  47:                 }
  48:                 else {
  49:                     // No data to calculate on
  50:                 }
  51:             }, false);
  52:             
  53:             // File uploaded
  54:             xhr.addEventListener("load", function () {
  55:                 progressBarContainer.className += " uploaded";
  56:                 progressBar.innerHTML = "Loaded!";
  57:             }, false);
  58:             
  59:             xhr.open("post", "upload/upload.php", true);
  60:             
  61:             // Set appropriate headers
  62:             xhr.setRequestHeader("Content-Type", "multipart/form-data");
  63:             xhr.setRequestHeader("X-File-Name", file.fileName);
  64:             xhr.setRequestHeader("X-File-Size", file.fileSize);
  65:             xhr.setRequestHeader("X-File-Type", file.type);
  66:             
  67:             
  68:             xhr.onreadystatechange = function() {
  69:                 if (xhr.readyState === 4) {
  70:                     if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
  71:                         alert(xhr.responseText);
  72:                         xhr = null;
  73:                     }
  74:                 }
  75:             }
  76:             
  77:             // Send the file (doh)
  78:             if ("getAsBinary" in file) {
  79:                 //FF 3.5+
  80:                 xhr.sendAsBinary(file.getAsBinary());
  81:             } else {
  82:                 xhr.send(file);
  83:             }
  84:             
  85:             
  86:             // Present file info and append it to the list of files
  87:             fileInfo = "<div><strong>Name:</strong> " + file.name + "</div>";
  88:             fileInfo += "<div><strong>Size:</strong> " + parseInt(file.size / 1024, 10) + " kb</div>";
  89:             fileInfo += "<div><strong>Type:</strong> " + file.type + "</div>";
  90:             div.innerHTML = fileInfo;
  91:             
  92:             fileList.appendChild(li);
  93:         }
  94:         
  95:         function traverseFiles (files) {
  96:             if (typeof files !== "undefined") {
  97:                 for (var i=0, l=files.length; i<l; i++) {
  98:                     uploadFile(files[i]);
  99:                 }
 100:             }
 101:             else {
 102:                 fileList.innerHTML = "No support for the File API in this web browser";
 103:             }    
 104:         }
 105:         
 106:         filesUpload.addEventListener("change", function () {
 107:             traverseFiles(this.files);
 108:         }, false);
 109:         
 110:         dropArea.addEventListener("dragleave", function (evt) {
 111:             var target = evt.target;
 112:             
 113:             if (target && target === dropArea) {
 114:                 this.className = "";
 115:             }
 116:             evt.preventDefault();
 117:             evt.stopPropagation();
 118:         }, false);
 119:         
 120:         dropArea.addEventListener("dragenter", function (evt) {
 121:             this.className = "over";
 122:             evt.preventDefault();
 123:             evt.stopPropagation();
 124:         }, false);
 125:         
 126:         dropArea.addEventListener("dragover", function (evt) {
 127:             evt.preventDefault();
 128:             evt.stopPropagation();
 129:         }, false);
 130:         
 131:         dropArea.addEventListener("drop", function (evt) {
 132:             traverseFiles(evt.dataTransfer.files);
 133:             this.className = "";
 134:             evt.preventDefault();
 135:             evt.stopPropagation();
 136:         }, false);                                        
 137:     })();
</script>

</body>
</html>

posted @ 2011-06-07 01:34  meteoric_cry  阅读(18592)  评论(3编辑  收藏  举报