文档章节

初识html5 File API实现带有进度提示的文件上传

m
 miscellanea
发布于 2014/06/27 11:08
字数 1398
阅读 26000
收藏 41

Html5终于解决了上传文件的同时显示文件上传进度的老问题。现在大部分的网站用Flash去实现这一功能,还有一些网站继续采用Html <form>with enctype=multipart/form-data,但是需要修改服务器端可用才能显示给用户文件上传的进度。本质上你需要做的工作是在服务器端接收一个文件时,你发送给它一个字节流,所以你需要知道你已经接收到多少字节并以某种方式传达这些信息给客户端浏览器,在这个过程一直在不断的进行文件的上传。这种方式运行的非常好,不像Flash上传那这样充满了问题(特别是处理大文件上传的时候),然而这种方法是相当复杂的并且听起来不容易理解,因为你本质上是接管了整个服务器端的处理(获取字节流的时候)同时包括了在服务器端实现multipart/form-data协议,伴随一系列的其他事情。

使用Html5 上传文件

XMLHttpRequest 在Html5 规范中已经有全新的变化,规定了XMLHttpRequest Level 2规范(目前最新版本)包含下列新的特性:

  1. 处理字节流,例如作为上传或者下载的File,Blob,FormData对象
  2. 上传或者下载中的进度事件
  3. 跨站点请求
  4. 允许创建匿名请求
  5. 可以设置请求超时

在这篇文章中我们将能够更清楚的看到#1和#2两个特性。通常,上传文件用XMLHttpRequest并且提供上传进度信息给最终的用户,需要注意的是这种方式解决了不需要服务器端做任何改变,至少是目前处理multipart/form-data协议。所以服务器端的处理逻辑保留不变,这使得开发者适应这种技术相当容易。

enter image description here 图1:文件上传画面-准备上传 enter image description here 图2:显示上传完成画面

注意:上面的图片中,信息提示区域是提供给用户的:

  1. 当前选中文件的信息
    • 文件名
    • 文件大小
    • 文件类型
  2. 上传完成多少的百分比进度条
  3. 上传速度或者上传带宽
  4. 距离上传完成大概还有多长时间
  5. 已上传文件大小
  6. 服务器端的响应

上面第6项或许看起来不重要,但事实上是相当重要的。因为我们用XMLHttpRequest,上传发生在后台,页面没有发生跳转等任何变化,所以对于你用它处理其他一些事情来说是一个非常好的特性。

Html5 Progress Event

对于Html5 Progress Events规范,Html5 Progess Events提供了下列与本次讨论相关的信息

  1. total - 总的字节数
  2. loaded - 到目前为止上传的字节数
  3. lengthComputable - 可计算的已上传字节

请注意到我们需要用两个信息去计算要显示给用户的其他所有信息。要计算出来其他的信息通过上面我们得到信息是相当容易的,但是那需要一些额外的代码并且创建一个定时器。

Html5 Progress Event 应该是什么

考虑到有一部分人想更好的提供给用户所有的信息,所以Html5 Progress Event应该更好的满足需要,因为它给浏览器供应商提供这些额外信息是相当简单的,所以建议progress event应该修改成如下:

  1. total - 总的字节数
  2. loaded - 到目前为止上传的字节数
  3. lengthComputable - 可计算的已上传字节
  4. transferSpeed long类型
  5. timeRemaining JavaScript 日期对象

Html5 上传 用XMLHttpRequest

浏览器支持情况

支持这一特性的浏览器最低版本

  1. Firefox 4.0 beta 6
  2. Chrome 6
  3. Safari 5.02

IE 9 Beta and Opera 10.62 不支持这一特性

简单的示例

下面是一个完整的Html页面包含了实现文件上传并带有进度提示的JavaScript代码,只是实现了基本的功能,感兴趣的可以自己做扩展。 需要吧上传接口修改成自己服务的。 

<!DOCTYPE html>
<html>
<head>
    <title>Upload Files using XMLHttpRequest - Minimal</title>
    <script type="text/javascript">
      function fileSelected() {
        var file = document.getElementById('fileToUpload').files[0];
        if (file) {
          var fileSize = 0;
          if (file.size > 1024 * 1024)
            fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
          else
            fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
          document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
          document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
          document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
        }
      }
      function uploadFile() {
        var fd = new FormData();
        fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
        var xhr = new XMLHttpRequest();
        xhr.upload.addEventListener("progress", uploadProgress, false);
        xhr.addEventListener("load", uploadComplete, false);
        xhr.addEventListener("error", uploadFailed, false);
        xhr.addEventListener("abort", uploadCanceled, false);
        xhr.open("POST", "upload.do");//修改成自己的接口
        xhr.send(fd);
      }
      function uploadProgress(evt) {
        if (evt.lengthComputable) {
          var percentComplete = Math.round(evt.loaded * 100 / evt.total);
          document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
        }
        else {
          document.getElementById('progressNumber').innerHTML = 'unable to compute';
        }
      }
      function uploadComplete(evt) {
        /* 服务器端返回响应时候触发event事件*/
        alert(evt.target.responseText);
      }
      function uploadFailed(evt) {
        alert("There was an error attempting to upload the file.");
      }
      function uploadCanceled(evt) {
        alert("The upload has been canceled by the user or the browser dropped the connection.");
      }
    </script>
</head>
<body>
  <form id="form1" enctype="multipart/form-data" method="post" action="Upload.aspx">
    <div class="row">
      <label for="fileToUpload">Select a File to Upload</label><br />
      <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/>
    </div>
    <div id="fileName"></div>
    <div id="fileSize"></div>
    <div id="fileType"></div>
    <div class="row">
      <input type="button" onclick="uploadFile()" value="Upload" />
    </div>
    <div id="progressNumber"></div>
  </form>
</body>
</html>



处于个人兴趣自己做了一个jsupload能够兼容目前主流浏览器,并实时显示文件上传进度,但是只能实现单文件上传。有关这个功能的更相信介绍请查看我的个人博客地址:  http://www.cnblogs.com/heikediguo/archive/2012/01/30/2332128.html

本文转载自:http://ux.sohu.com/topics/4ff177586c423d2471000725

共有 人打赏支持
m
粉丝 6
博文 86
码字总数 22525
作品 0
海淀
私信 提问
加载中

评论(3)

全球通
全球通
不知道为什么,chrome浏览器桌面版,xhr.upload.onprogress 事件只是在数据传输完毕之后才触发一次。
透明如风
腻害
imlzw
imlzw
79,解决我目前的问题
(转载学习)文件上传的渐进式增强

本文为转载学习 原文作者:阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/08/fileupload.html HTML5提供了一系列新的浏览器API,使得文件上传有可能出现革命性变化。英国程序员Rem...

heroShane
2014/01/24
0
0
7款基于JavaScript和AJAX的文件上传插件

本文整理了7款基于JavaScript和AJAX的文件上传插件,这些插件基本上都能实现以下功能: 多文件上传 拖拽操作 实时上传进度 自定义上传限制 希望能为你的开发工作带来帮助。 1. jQuery File U...

EDIAGD
2013/09/23
0
0
使用jQuery开发一个基于HTML5的漂亮图片拖拽上传web应用

日期:2011/11/19 来源:GBin1.com 昨天我们介绍了一款HTML5文件上传的jQuery插件:jQuery HTML5 uploader ,今天我们将开发一个简单的叫upload center的图片上传程序,允许用户使用拖拽方式...

gbin1
2011/11/19
0
1
基于HT for Web矢量实现HTML5文件上传进度条

在HTML中,在文件上传的过程中,很多情况都是没有任何的提示,这在体验上很不好,用户都不知道到时有没有在上传、上传成功了没有,所以今天给大家介绍的内容是通过HT for Web矢量来实现HTML5...

xhload3d
2015/06/08
0
0
转:XMLHttpRequest2 新技巧

”XMLHttpRequest 的异步调用网上找的例子运行没问题,但稍微改了一点点就报错”InvalidStateError: XMLHttpRequest has an invalid context“。断断续续 搞了3天终于通了,可以接收二进制文...

SamXIAO
09/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

MariaDB 服务器在 MySQL Workbench 备份数据的时候出错如何解决

服务器是运行在 MariaDB 10.2 上面的,在使用 MySQL Workbench 出现错误: mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"'......

honeymose
今天
2
0
apache顶级项目(二) - B~C

apache顶级项目(二) - B~C https://www.apache.org/ Bahir Apache Bahir provides extensions to multiple distributed analytic platforms, extending their reach with a diversity of s......

晨猫
今天
6
0
day152-2018-11-19-英语流利阅读

“超级食物”竟然是营销噱头? Daniel 2018-11-19 1.今日导读 近几年来,超级食物 superfoods 开始逐渐走红。不难发现,越来越多的轻食餐厅也在不断推出以超级食物为主打食材的健康料理,像是...

飞鱼说编程
今天
12
0
SpringBoot源码:启动过程分析(二)

接着上篇继续分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 一样的,我们先把时序图贴上来,方便理解: 二.源码分析 回顾一下,前面我们分析到了下...

Jacktanger
昨天
4
0
Apache防盗链配置,Directory访问控制,FilesMatch进行访问控制

防盗链配置 通过限制referer来实现防盗链的功能 配置前,使用curl -e 指定referer [root@test-a test-webroot]# curl -e "http://www.test.com/1.html" -x127.0.0.1:80 "www.test.com/1.jpg......

野雪球
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部