Web applications often need to provide the ability to upload files. Typical scenes include user avatar upload, photo album upload and so on. When you need to upload a larger file, it is necessary to provide a progress bar showing the progress of the upload.
Before PHP 5.4, the implementation of such a progress bar is not easy, there are mainly three ways:
1. Use Flash, Java, ActiveX
2. Using the APC extension in PHP
3. Using the HTML5 file API
The first approach relies on Third-party browser plug-ins, which are not universal, and are easy to bring security risks. However, because of the wide use of flash, there are many sites using flash as a solution.
The disadvantage of the second approach is that it requires the installation of the APC extension library in PHP, requiring users to be able to control server-side configuration. In addition, if the APC is installed only to implement an upload progress bar, then obviously a bit overkill meaning.
The third approach should be the most ideal approach, with no server-side support, only javascript on the browser side. However, because the HTML5 standard has not been established, the support of the browser vendors are not the same, so the temporary method is still difficult to popularize.
The session-based Upload progress monitoring feature (session.upload_progress), introduced in PHP 5.4, provides a server-side upload progress monitoring solution. After you upgrade to PHP 5.4, you can upload a progress bar without having to install an APC extension and use only native PHP and front-end JavaScript.
Let's take a look at the new session.upload_progress features of PHP 5.4 in detail.
Principle Introduction
When the browser uploads a file to the server side, PHP will store the details of the file upload (such as upload time, upload progress, etc.) in the session. Then, as the upload progresses, periodically updates the information in the session. This allows the browser side to use Ajax periodically to request a server-side script that returns progress information from the session, and the browser-side JavaScript can display/update the progress bar based on that information.
So, how is the file upload information specifically stored? How do we access it? Let's go into the details below.
Some configuration items are introduced in PHP 5.4 (set in php.ini)
Copy Code code 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"
The Enabled control Upload_progress function is open or not, the default is open; cleanup sets the information for the session to be cleared when the file upload request is completed, which is opened by default.
The variable name/key name used by prefix and name two to set the progress information stored in the session. Detailed use of these two items is shown below.
Freq and Min_freq two are used to set the frequency at which server-side progress information is updated. A reasonable set of these two items can reduce the burden on the server.
In the form that uploads the file, you need to set an identifier for the upload and use that identifier to refer to the progress information in the following procedure. Specifically, there needs to be a hidden input in the upload form, and its Name property is the value of the session.upload_progress.name in php.ini; its value is an identifier that you define yourself. As follows:
Copy Code code as follows:
<input type= "hidden"
Name= "<?php Echo ini_get (' Session.upload_progress.name ');?>"
value= "Test"/>
After receiving the file Upload form, PHP creates a new key in the $_session variable, and the key name is a string that connects the value of the Session.upload_progress.prefix to your custom identifier above, so you can get:
Copy Code code as follows:
$name = Ini_get (' Session.upload_progress.name ');
$key = Ini_get (' Session.upload_progress.prefix '). $_post[$name];
$_session[$key]; This is the progress information for this file upload.
$_session[$key] The structure of this variable is this:
Copy Code code as follows:
$_session["upload_progress_test"] = Array (
"Start_time" => 1234567890,//Start time
Total data length for "content_length" => 57343257,//POST request
"Bytes_processed" => 453489,//received length of data
"Done" => false,//Request completion True indicates completion, false incomplete
Information for a single file
"Files" => Array (
0 => Array (...),
Multiple files can be included in the same request
1 => Array (...),
)
);
In this way, we can use the Content_length and bytes_processed two items to get a progress percentage.
program Example
After the introduction of the principle, we will complete the implementation of a PHP and JavaScript based file upload progress bar.
Upload a form
First, to write our upload form page index.php, the code is as follows:
Copy Code code as follows:
<form id= "Upload-form"
action= "upload.php" method= "POST" enctype= "Multipart/form-data"
Style= "margin:15px 0" target= "hidden_iframe" >
<input type= "hidden" name= "" value= "test"/>
<p><input type= "File" Name= "File1"/></p>
<p><input type= "Submit" value= "Upload"/></p>
</form>
<iframe id= "Hidden_iframe" name= "Hidden_iframe" src= "About:blank" style= "Display:none"; ></iframe>
<div id= "Progress" class= "Progress" style= "Margin-bottom:15px;display:none"; >
<div class= "Bar" style= "width:0%;" ></div>
<div class= "label" >0%</div>
</div>
Note the Session.upload_progress.name hidden item in the form, and the value is set to test. There is only one file in the form to upload input, and if necessary, you can add multiple.
Here you need to pay special attention to the target property of the form, which is set to point to an IFRAME on the current page. This is critical by setting the target property so that the form's submitted page appears in the IFRAME, avoiding the current page jump. Because we still have to show the progress bar on the current page.
#progress This div is used to display the progress bar.
Be careful not to forget to add session_start () at the beginning of the index.php.
Process uploaded files
The action of the form points to upload.php, where we process the uploaded file in upload.php and dump it into the current directory. This is no different from the usual uploading process.
Copy Code code as follows:
if (Is_uploaded_file ($_files[' file1 '] [' tmp_name '])) {
Move_uploaded_file ($_files[' file1 '] [' tmp_name '], "./{$_files[' file1 '] [' name ']}");
}
?>
Ajax Get Progress Information
This step is the key, we need to create a progress.php file, to read the session of progress information; We then add JavaScript code to the index.php, launch an AJAX request to progress.php, and update the progress bar based on the progress information obtained.
The code for progress.php is as follows:
Copy Code code as follows:
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;
}
?>
Here we get the progress information in the $_session variable and then output a percent of progress.
In index.php, we add the following code to the bottom of the page (for simplicity, use jquery here):
Copy Code code as follows:
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 (' Finish! ');
}
}, ' html ');
}
$ (' #upload-form '). Submit (function () {
$ (' #progress '). Show ();
SetTimeout (' fetch_progress () ', 100);
});
When #upload-form is submitted, we display the progress bar, and then repeatedly call Fetch_progress () to get progress information and update the progress bar until the file is uploaded, showing ' Finish! '.
done!
Complete code Download: Http://xiazai.jb51.net/201410/tools/samples-master.rar
Attention matters
Position of input label
The input label named Session.upload_progress.name must be placed in front of the file input <input type= "file"/>.
Cancel Upload
By setting the $_session[$key] [' cancel_upload '] = True to cancel the secondary upload. You can only cancel files that are being uploaded and files that have not yet started. Files that have been uploaded successfully will not be deleted.
SetTimeout vs. SetInterval
Fetch_progress () should be invoked by settimeout (), which ensures that the next request is not started until a request is returned. If using setinterval () does not guarantee this, it may cause the progress bar to appear ' not in reverse '.