A problem that has been bothering web developers for many years is how to add real-time information to their applications, such as file upload progress bars. Users are impatient, they don't want to sit around and wait while the browser is doing something, wondering if it's frozen or if they have a slow connection. Provides a progress indicator to provide useful information to the user and let them know exactly what is going on.
At first thought, you might think that accomplishing this could easily be done by first getting the size of the file from the user's computer and then doing some simple calculations on the directory under which the file is being uploaded to the server. Regarding the second thought, you will find that things are not as simple as you think.
JavaScript can access a file's name, type, and even the width and height of native images, but it wasn't until HTML5 that it can access a file's size. Unfortunately, HTML5 is still an unfinished standard yet and is not uniformly supported across all browsers. Another solution is to rely on a Flash, Java or ActiveX plugin installed, no thanks, I'll pass that. Another solution is to install the optional PHP caching extension, but depending on your hosting environment it may not be available, which may seem like overkill for such a small task like this one.
It seems like all the options are full of nuisances and the mission has quickly become a headache. But in the words of Yoda, "There is not...and one."
There are many reasons why I love PHP is that it makes seemingly difficult tasks very easy. In PHP 5.4, they have done session.upload_progress again with a new set of configuration options.
In this article, I will show you how this functionality can be used to create a simple upload progress bar without any external libraries or browser dependencies. I'll first discuss how it works, and then I'll walk you through creating the four files needed to complete the task (an upload form, some JavaScript, a little CSS, and a file return loaded status).
Meeting Upload Progress
In addition to the usual requirements to allow file uploads, there are two more to track progress. The session.upload_progress.enabled directive must be enabled, and there must be a hidden field in the web form with the name specified by the session.upload_progress.name directive. When session.upload_progress.enabled is true (as it is by default in PHP 5.4 and presumably later) and $_POST[session.upload_progress.name ] is available in the $_SESSION superglobal regarding file transfer uploads, array.
The $_SESSION array output by print_r() looks similar to the following during a file transfer:
Array ( [upload_progress_myForm] => Array ( [START_TIME] => 1323733740 [CONTENT_LENGTH] => 721127769 [ bytes_processed] => 263178326 [Complete] => [File] =>array ([0] =>array ([FIELD_NAME] => USERFILE [name] =>ubuntu-10.04.3-desktopi386 .iso [value of tmp_name] => [Error] => 0 [Complete] => [START_TIME] => 1323733740 [bytes_processed] => 263178026 ) ) ) ) )
When you are developing locally or On a fast network, and uploading small files, you won't be able to visually observe the progress because the transfer happens so quickly. In this case, you may want to try transferring large files. Make sure you set up your php.ini file to allow larger uploads, specifically the post_max_size and upload_max_filesize directives, and then confirm they are sane values when you go to production.
Creating Forms
The first file I will cover is the upload form. Just to keep things as simple as possible, this example will be posted so that it can only handle one file upload at a time. Also, I wouldn't bother saving the file after it has been uploaded.
Here is the code for form.php:
<?PHP 如果($ _SERVER [ “REQUEST_METHOD” ] == “POST” &&!空($ _FILES [ “userfile的” ])){ / / move_uploaded_file()以 } ?> <HTML> <HEAD> <TITLE>文件上传进度条</ TITLE> <链接相对= “样式表” 类型= “文/ CSS” HREF = “style.css文件” > </ HEAD> <BODY> <分区编号= “bar_blank” > <分区编号= “bar_color” > </ DIV> </ DIV> <分区编号= “状态” > </ DIV> <形式的行动= “<PHP的回声$ _SERVER?[” PHP_SELF “];?>” 方法= “POST” ID = “myForm的” 是enctype = “多部分/窗体的数据” 目标= “hidden_iframe” > <输入类型= “隐藏” 值= “myForm的” 名称= “<?PHP的回声ini_get(” session.upload_progress.name ?“);>” > <输入类型= “文件” 名称= “USERFILE” > <BR> <输入类型= “提交” 值= “开始上传” > </ FORM> <iframe的ID = “hidden_iframe” 名称= “hidden_iframe” SRC = “关于:空白” > </ IFRAME> <脚本类型= “文/ JavaScript的” SRC = “的script.js” > </ SCRIPT> </ BODY> </ HTML>
In this example the code to actually process the file has been omitted to keep things simple. If you are interested in what such code should look like, check out the article File Uploading with PHP by Timothy Boronczyk.
After the header section, which provides the title of the page and includes the stylesheet, you will find a small collection of div elements. The DIV with the ID "bar_blank" is the progress bar of the container. The div with the ID "bar_color" will dynamically update the file upload progress. The "Status" div will display the percent uploaded value.
该窗体设置为提交给同一个URL,并将其目标属性指向一个隐藏的iframe元素。 提交表单到一个隐藏的框架可以让你保持访问者在同一页上,而工作在后台正在做。 其实,这是一种常见的做法做“的Ajax文件上传”的时候,因为它是不可能直接发送使用JavaScript的一个文件的内容XmlHttpRequest对象。
在表格中,特殊的隐藏字段需要填充$_SESSION数组,接着出现一个文件上传输入和提交按钮。 提交表单将触发一个名为JavaScript函数startUpload()将被包含的JavaScript文件中定义。
在页面的底部是隐藏的框架,其形式将发布和进口script.js文件。
添加一些样式
下一个文件, style.css ,是相当直接的。 我定义的进度条容器的大小并给予它一个1px的黑色边框,进度条的颜色,因为它的加载,无论是IFRAME和进度条是隐藏的。
#bar_blank { 边界:固体1px的#000 ; 高度:20像素; 宽度:300像素; } #bar_color { 背景色:#006666 ; 高度:20像素; 宽度:0PX ; } #bar_blank,#hidden_iframe { 显示:无; }
客户端功能
该script.js文件是最大的组文件。 它包含六大功能,我将在下面讨论。 很多人喜欢用jQuery来提供一些功能在这里,你当然可以这样做,如果你愿意的话,但我个人更喜欢老派的做法。 类似于如何日本人放在手工制作的货物价值较高的,我只是觉得更热衷于代码,如果是我自己。
功能toggleBarVisibility(){ 变种E =的document.getElementById(“bar_blank” ); e.style.display =(e.style.display == “块” ?) “ 无” :“块” ; } 功能createRequestObject(){ 变种的http; 如果(navigator.appName == “Microsoft Internet Explorer的” ){ HTTP = 新的ActiveXObject(“Microsoft.XMLHTTP” ); } 否则{ HTTP = 新的XMLHttpRequest(); } 返回的http; } 功能sendRequest将(){ 变种的http = createRequestObject(); http.open(“GET” ,“progress.php” ); http.onreadystatechange = 函数(){用handleResponse(HTTP);}; http.send(空); } 功能用handleResponse(HTTP){ 无功响应; 如果(http.readyState == 4){ 响应= http.responseText; 的document.getElementById(“bar_color” 。)共0则回应+ “%” ; 的document.getElementById( “ 地位” 。)的innerHTML =响应+ “%” ; 如果(响应<100){ 的setTimeout(“sendRequest将()” ,1000); } 否则{ toggleBarVisibility(); 的document.getElementById( “ 地位” 。)的innerHTML = “Done(完成)。” ; } } } 功能startUpload(){ toggleBarVisibility(); 的setTimeout(“sendRequest将()” ,1000); } (函数(){ 的document.getElementById(“myForm会” )的onsubmit = startUpload; })();
该toggleBarVisibility()函数上的“bar_blank”的div根据需要显示或隐藏进度条设置合适的样式。 最初,它开始时隐藏,但会一次上传开始出现,然后再次隐藏当上载完成。
该createRequestObject()函数创建一个XMLHttpRequest或ActiveXObject根据用户的浏览器对象。 这可能是该功能大多数人都期待的jQuery或其他一些JavaScript框架来提供。
该sendRequest()函数请求progress.php文件与一个GET请求,然后调用handleResponse()函数来处理返回的数据。
该handleResponse()函数处理从响应progress.php这将是依赖于文件上传进度多项1-100之间。 我也更新了“状态”的div适当的值。 如果电流的百分比低于100然后调用JavaScript的原生setTimeout()函数来1秒后发送的更新另一个请求(你可能需要调整该值如适用),否则我再次隐藏进度条和状态设置为“完成”。
该startUpload()函数使得载栏可见,并发送一个更新请求的1秒的延迟。 这个小的延迟是必要的,为了给上传时间才能启动。
最后一个功能是一个自执行的匿名函数,它注册startUpload()与表单的提交事件。
实时进展
带来一切融合在一起的最后一个文件是progress.php文件:
<?PHP 在session_start(); 美元的关键= ini_get (“session.upload_progress.prefix” )。“myForm的” ; 如果(!空($ _SESSION [ $关键])){ $电流= $ _SESSION [ $关键] [ “bytes_processed” ]; 共$ = $ _SESSION [ $关键] [ “CONTENT_LENGTH” ]; 回声$电流< $总?CEIL ($电流/ $总量* 100):100; } 否则{ 回声100; }
该脚本执行上传输的字节数目前在总文件大小,再乘以100,并四舍五入到给一个百分比分成一些简单的数学。
有关传输的信息,关键在于有一套与session.upload_progress.prefix指令的值的串联和隐藏session.upload_progress.name字段的值。 因为我的形式通过了“myForm会”,会议的重点是与确定ini_get("session.upload_progress.prefix") . "myForm"ini_get("session.upload_progress.prefix") . "myForm" 。
下面是在行动进度条的截图:
微调行为
PHP提供了一些额外的指令来帮助微调会话上传的行为,你应该知道的。 例如,session.upload_progress.cleanup ,这是默认设置为1,清理后,立即上传已经完成了额外的会话数据。 你必须要小心,以避免潜在的竞争条件。
再看看在代码progress.php ,你会发现,我检查,看看是否$_SESSION[$key]为空或不是,然后再继续。我的JavaScript函数火了每一秒,只要结果从返回progress.php小于100。 如果session.upload_progress.cleanup已启用,我的脚本获取99%的上传和1/2-second后上传完成后,$_SESSION[$key]不会为下一个检查存在的。 如果我不考虑到这一点,然后我的JavaScript函数可能保持射击,上传完成之后也是如此。
The other two directives are session.upload_progress.freq and session.upload_progress.min_freq which determine how often the session should be updated. The value of frequency can be given in either byte (i.e. 100) or as a percentage of the total number of bytes (i.e. 2%). The value of min_freq is in seconds and represents the minimum number of seconds between updates. Obviously, if min_freq is set to update every 1 second, it would be pointless for JavaScript to check every 100 milliseconds.
Summary
You should now have a firm grasp on how to create a file upload progress bar using the session upload progress feature. Going forward, I encourage you to try uploading multiple files, giving the option to cancel an upload in progress using $_SESSION[$key]["cancel_upload"] , or any other ideas your mind can muster.