HTML 5应用实战:灵活拖拉文件(1)


这篇文章将分如下几个方面进行初步的分析和探讨:


◆ 如何将文件拖放到web页面中


◆ 在Javascript中分析拖拽文件


◆ 在客户端装载和解析文件


◆ 使用 XMLHttpRequest2异步上传文件到服务端


◆ 上传时显示一个进度条


◆ 改进上传文件的表单,甚至支持IE 6,以让在各浏览器中可以兼容运行。


◆ 并介绍如何单单只用Javascript实现,不用任何框架。


目前浏览器对文件拖拉的支持


在我们开始讲解前,我们先要说明下,由于HTML5的标准最终版本还没完全发布,各浏览器也不是完全都对所有功能进行支持,所以本文的程序有可能在今后的各浏览器中不能完全运行成功,但至少在本文发表时,会对以下浏览器在如下各方面进行支持。


1) 目前程序能在所有的Firefox和Chrome的浏览器中很好的运行。


2) Opera浏览器能解通过Javascript去解析文件,但不支持文件的拖拉到浏览器中及使用XMLHttpRequest2去上传文件。


3) IE和Safari不支持任何本文提到的API和新特性。


4) Apple不允许在iOS系统中使用HTML表单上传文件。


下面,就让我们开始学习之旅吧。


HTML和CSS


我们先来看下上传文件的表单,代码如下:


  1. <form id="upload" action="upload.php" method="POST" enctype="multipart/form-data"> 
  2. <fieldset> 
  3. <legend>HTML File Upload</legend> 
  4. <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="300000" /> 
  5. <div> 
  6.     <label for="fileselect">Files to upload:</label> 
  7.     <input type="file" id="fileselect" name="fileselect[]" multiple="multiple" /> 
  8.     <div id="filedrag">or drop files here</div> 
  9. </div> 
  10. <div id="submitbutton"> 
  11.     <button type="submit">Upload Files</button> 
  12. </div> 
  13. </fieldset> 
  14. </form> 
  15. <div id="messages"> 
  16. <p>Status Messages</p> 
  17. </div> 

可以看到,在这个表单中,放置了一个文件选择框,唯一跟HTML4不同的时,这个框采用的是HTML5中的一个新增的文件上传框属性multiple,允许选择多个不同的文件。此外,在id为 filedrag的div中,这个区域是用来将文件拖拉放置的区域,下文中会用到。


接下来会看下CSS,代码如下:


  1. #filedrag  
  2. {  
  3. display: none;  
  4. font-weight: bold;  
  5. text-align: center;  
  6. padding: 1em 0;  
  7. margin: 1em 0;  
  8. color: #555;  
  9. border: 2px dashed #555;  
  10. border-radius: 7px;  
  11. cursor: default;  
  12. }  
  13. #filedrag.hover  
  14. {  
  15. color: #f00;  
  16. border-color: #f00;  
  17. border-style: solid;  
  18. box-shadow: inset 0 3px 4px #888;  
  19. }  

在这段CSS中,设置了当文件拖放到页面的指定区域时的样式,这个样式是当文件被拖动到指定区域时,才起到作用的,是通过Javascript击发其起作用的,下文会提到。


HTML5中的文件API


在HTML5中,对文件的API有如下几点的新的改进,其标准可以参考(http://www.w3.org/TR/file-upload/)。


FileList: 表示已选择的文件,以数组的形式表示。


File: 代表一个单独的文件


FileReader: FileReader是一个接口,它允许我们在客户端读取文件的数据,并且可以在Javascript中去使用。


开始动手写Javascript


下面,我们开始动手编写Javascript,首先我们编写一些工具javascript,比如:


  1. // getElementById  
  2. function $id(id) {  
  3. return document.getElementById(id);  
  4. }  
  5. //  
  6. // 输出信息  
  7. function Output(msg) {  
  8. var m = $id("messages");  
  9. m.innerHTML = msg + m.innerHTML;  

接者,我们编写init方法,去判断文件API的可用性,代码如下:


  1.  // 判断当前浏览器中文件API是否可用  
  2. if (window.File && window.FileList && window.FileReader) {  
  3. Init();  
  4. }  
  5. //  
  6. // 初始化程序  
  7. function Init() {  
  8. var fileselect = $id("fileselect"),  
  9. filedrag = $id("filedrag"),  
  10. submitbutton = $id("submitbutton");  
  11. // 添加文件选择的事件监听  
  12. fileselect.addEventListener("change", FileSelectHandler, false);  
  13. // 判断xmlhttprequest 2是否可用  
  14. var xhr = new XMLHttpRequest();  
  15. if (xhr.upload) {  
  16. // file drop  
  17. filedrag.addEventListener("dragover", FileDragHover, false);  
  18. filedrag.addEventListener("dragleave", FileDragHover, false);  
  19. filedrag.addEventListener("drop", FileSelectHandler, false);  
  20. filedrag.style.display = "block";  
  21. // remove submit button  
  22. submitbutton.style.display = "none";  
  23. }  

程序中,首先判断当前浏览器中文件API是否可用,如果可用的话则调用init的初始方法。在init方法中,做了如下几件事情:


为文件的选择框增加了上传的监听事件。


显示#filedrag区域


设置了拖动文件经过放置区域时和文件离开放置区域时的事件以及样式。


设置了当用户将文件拖动到放置区域最后松开鼠标,以决定文件放置时的事件。


这里还隐藏了提交按钮,因为这里并不需要它了。


当然,这里还可以连传统的文件上传浏览框也去掉,但这并不是十分友好,所以这里采用的是两者并存的方式。


而用到了XMLHttpRequest的upload方法,主要是防止在一些浏览器中如果当文件上传API不可用时,则用旧的方法,不显示文件拖拉框,取而代之的是显示传统的上传提交按钮。


考虑到很少用户很熟悉文件的这种拖拉上传用法,因此,我们在事件中对文件放置区域的样式进行设置,当文件被拖拉到区域中时,区域的边框会变成红色,以提醒用户,代码如下:


  1. function FileDragHover(e) {  
  2. e.stopPropagation();  
  3. e.preventDefault();  
  4. e.target.className = (e.type == "dragover" ? "hover" : "");  
  5.  } 

这里判断是否文件拖拉到区域上方,如果是的话,则采用样式中的hover样式。


接下来,我们会在另外的一个div区域中,显示文件上传的小结信息,代码如下:


  1. function FileSelectHandler(e) {  
  2. FileDragHover(e);  
  3. // 获得所有的文件列表  
  4. var files = e.target.files || e.dataTransfer.files;  
  5. // 循环处理每个文件  
  6. for (var i = 0, f; f = files[i]; i++) {  
  7. ParseFile(f);  
  8. }  
  9. }  

在FileSelectHandler事件中,实现了如下的功能:


1 调用FileDragHover()方法移除了hover的样式,并且取消浏览器的响应事件,否则的话浏览器会尝试显示文件的内容。


2 将上传的文件放置到FileList对象数组中去,包括用传统文件上传框上传的及用拖拉方法上传的。


3 单独使用一个方法ParseFile输出上传每个文件的具体属性信息,代码如下;


  1. function ParseFile(file) {  
  2. Output(  
  3. "  
  4. File information: " + file.name +  
  5. " type: " + file.type +  
  6. " size: " + file.size +  
  7. " bytes  
  8. "  
  9. );  




标签:

友情链接
轻松育儿世界奇观
苏ICP备16066217号-2