好的, 这是一篇让您 "虎须一震" 的文章。相信您已经为显示文件上传进度而头痛很久了。不过先别高兴得太早, 您手上的 Web 框架通常不支持进度条技术。哈哈哈哈。
得到上传文件的大小很好。要显示进度条的关键是得到上传文件的大小。这个问题曾经也让在下晕乎了一下下, 因为我搜了一下 Google, 大家都说要 ActiveX 或者类似 Applet、Flash 这样的插件, 因为据说浏览器没有读取本地文件大小的权限。好了, 别理他们, 我这就告诉你无插件获取上传文件大小的方法。你看文件上传的报文:
POST / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, application/vnd.ms-powerpoint, */*
…
Content-Type: multipart/form-data; boundary=---------------------------7d439d362703b2
…
Cache-Control: no-cache
-----------------------------7d439d362703b2
Content-Disposition: form-data; name="test_file"; filename="xxx"
Content-Type: text/plain
1234abcd!@#$()-=:”
-----------------------------7d439d362703b2--
从 ”-----------------------------7d439d362703b2“ 开始就是 HTTP Body 了, 这部分的长度我们是可以得到的, 不错, 就是 'Content-Length'。很不幸文件的长度就是 Content-Length 减去两个分割线 '-----------------------------7d439d362703b2' 再减去子报文的头部 'Content-Disposition: form-data; name="test_file"; filename="xxx"\nContent-Type: text/plain' 剩下的长度。
很容易做到不是吗?
得到已上传数据大小, 并从另一条 HTTP 连接返回进度实在没办法的话, 将上传数据写入临时文件, 并且立即 flush。这样你就可以通过 AJAX 定时去获取临时文件的大小, 计算出进度并返回。很好, 恶心得没话说。
略好的方法是使用应用服务器建立两个可以互相通信的线程, 建立两条长连接, 一条负责上传, 一条负责返回上传进度。上传线程可以累加已上传内容的大小, 供另一个反馈线程使用。当然协作线程会好很多, 否则你的应用可能只能支持不到 10 个用户同时上传文件。
恭喜您显然您的 Web 框架不支持进度条显示, 马上升级你的技术吧。