Web applications often need to provide file upload functions. Typical scenarios include uploading user avatars, uploading album pictures, etc. When the file to be uploaded is relatively large, it is necessary to provide a progress bar showing the upload progress.
Before PHP 5.4, it was not easy to implement such a progress bar. There were three main methods:
Use Flash, Java, ActiveX
Using PHP's APC extension
Using HTML5's File API
Related learning recommendations:PHP Programming from beginner to master
The first method relies on third-party browser plug-ins, which is not versatile enough and can easily bring security risks. However, due to the widespread use of Flash, there are still many websites that use Flash as a solution.
The disadvantage of the second method is that it requires the installation of PHP's APC extension library and requires the user to control the server-side configuration. In addition, if APC is installed just to implement an upload progress bar, then it is obviously a bit overkill.
The third method should be the most ideal method. It does not require server-side support and only uses Javascript on the browser side. However, since the HTML5 standard has not yet been established and the support of various browser manufacturers is different, this method is still difficult to popularize.
The session-based upload progress monitoring function (session.upload_progress) introduced in PHP 5.4 provides a server-side upload progress monitoring solution. After upgrading to PHP 5.4, you don't need to install the APC extension. You can implement the upload progress bar using only native PHP and front-end Javascript.
Let’s introduce the session.upload_progress new feature of PHP 5.4 in detail.
Principle introduction
When the browser uploads a file to the server, PHP will upload the detailed information of the file (such as upload time, upload progress, etc. ) is stored in the session. Then, as the upload progresses, the information in the session is periodically updated. In this way, the browser can use Ajax to periodically request a server-side script, and the script returns the progress information in the session; the browser-side Javascript can display/update the progress bar based on this information.
So, how is the file upload information stored? How do we access it? Let’s explain in detail below.
PHP 5.4 introduced some configuration items (set in php.ini)
The code is as follows:
session.upload_progress.enabled = "1" session.upload_progress.cleanup = "1" session.upload_progress.prefix = "upload_progress_" session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" session.upload_progress.freq = "1%" session.upload_progress.min_freq = "1"
enabled controls whether the upload_progress function is turned on or not, the default Enable; cleanup sets whether to clear session-related information after the file upload request is submitted. It is enabled by default.
The prefix and name are used to set the variable name/key name of the progress information stored in the session. See below for detailed usage of these two items.
freq and min_freq are used to set the frequency of updating progress information on the server side. Properly setting these two items can reduce the load on the server.
In the form for uploading files, you need to set an identifier for this upload and use this identifier to reference progress information in the subsequent process. Specifically, there needs to be a hidden input in the upload form, whose name attribute is the value of session.upload_progress.name in php.ini; its value is an identifier defined by yourself. As follows:
The code is as follows:
After receiving the file upload form, PHP will create a new key in the $_SESSION variable. The key name is the value of session.upload_progress.prefix and the above The string obtained after concatenating your custom identifier can be obtained like this:
The code is as follows:
$name = ini_get('session.upload_progress.name'); $key = ini_get('session.upload_progress.prefix') . $_POST[$name]; $_SESSION[$key]; // 这里就是此次文件上传的进度信息了
$_SESSION[$key]
The structure of this variable is Like this:
The code is as follows:
$_SESSION["upload_progress_test"] = array( "start_time" => 1234567890, // 开始时间 "content_length" => 57343257, // POST请求的总数据长度 "bytes_processed" => 453489, // 已收到的数据长度 "done" => false, // 请求是否完成 true表示完成,false未完成 // 单个文件的信息 "files" => array( 0 => array( ... ), // 同一请求中可包含多个文件 1 => array( ... ), ) );
In this way, we can use the two items content_length and bytes_processed to get the progress percentage.
Program Example
Now that the principle has been introduced, let’s completely implement a file upload progress bar based on PHP and Javascript.
Upload form
First, write our upload form page index.php, the code is as follows:
The code is as follows:
0%
Pay attention to the hidden item session.upload_progress.name in the form, and the value is set to test. There is only one file upload input in the form, you can add multiple if needed.
You need to pay special attention to the target attribute of the form. The setting here points to an iframe in the current page. This is crucial. By setting the target attribute, the page after the form is submitted is displayed in the iframe, thereby avoiding the current page jump. Because we still have to display the progress bar on the current page.
#progress
This p is used to display the progress bar.
Note: Don’t forget to add session_start() at the beginning of index.php.
Processing uploaded files
The action of the form points to upload.php. We process the uploaded file in upload.php and transfer it to the current directory. There is no difference from the normal upload processing here.
代码如下:
if(is_uploaded_file($_FILES['file1']['tmp_name'])){ move_uploaded_file($_FILES['file1']['tmp_name'], "./{$_FILES['file1']['name']}"); } ?>
Ajax获取进度信息
这一步是关键,我们需要建立一个 progress.php 文件,用来读取session中的进度信息; 然后我们在 index.php 中增加Javascript代码,向 progress.php 发起Ajax请求,然后根据获得的进度信息更新进度条。
progress.php 的代码如下:
代码如下:
session_start(); $i = ini_get('session.upload_progress.name'); $key = ini_get("session.upload_progress.prefix") . $_GET[$i]; if (!empty($_SESSION[$key])) { $current = $_SESSION[$key]["bytes_processed"]; $total = $_SESSION[$key]["content_length"]; echo $current < $total ? ceil($current / $total * 100) : 100; }else{ echo 100; } ?>
在这里我们获得$_SESSION变量中的进度信息,然后输出一个进度百分比。
在 index.php 中,我们将如下代码添加到页面底部 (为简便,这里使用jQuery):
代码如下:
function fetch_progress(){ $.get('progress.php',{ '' : 'test'}, function(data){ var progress = parseInt(data); $('#progress .label').html(progress + '%'); $('#progress .bar').css('width', progress + '%'); if(progress < 100){ setTimeout('fetch_progress()', 100); }else{ $('#progress .label').html('完成!'); } }, 'html'); } $('#upload-form').submit(function(){ $('#progress').show(); setTimeout('fetch_progress()', 100); });
当#upload-form被提交时,我们把进度条显示出来,然后反复调用 fetch_progress() 获得进度信息,并更新进度条,直到文件上传完毕,显示'完成!'。
注意事项
input标签的位置
name为session.upload_progress.name的input标签一定要放在文件input的前面。
取消上传
通过设置 $_SESSION[$key]['cancel_upload'] = true 可取消当次上传。但仅能取消正在上传的文件和尚未开始的文件。已经上传成功的文件不会被删除。
setTimeout vs. setInterval
应该通过 setTimeout() 来调用 fetch_progress(),这样可以确保一次请求返回之后才开始下一次请求。如果使用 setInterval() 则不能保证这一点,有可能导致进度条出现'不进反退'。
The above is the detailed content of Learn to use Session and Javascript to implement the file upload progress bar function in PHP. For more information, please follow other related articles on the PHP Chinese website!