Using Session and Javascript in PHP to Realize the Function of File Upload Progress Bar

  • 2021-07-22 09:11:23
  • OfStack

Web applications often need to provide the function of uploading files. Typical scenes include uploading user avatars, uploading photo albums and so on. When the file needs 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, and there were three main methods:

1. Use Flash, Java, ActiveX
2. APC extensions using PHP
3. File API with HTML5

The first method relies on the browser plug-in of the third party, which is not universal and easy to bring potential safety hazards. However, due to the wide use of Flash, there are still many websites using Flash as a solution.

The disadvantage of the second method is that it requires the installation of the APC extension library for PHP and requires the user to be able to control the configuration on the server side. In addition, if APC is installed only to realize an upload progress bar, it is obviously a bit of a kill.

The third method should be the most ideal method, which does not need server-side support, and only uses Javascript on the browser side. However, because the HTML5 standard has not yet been established and the support of different browser manufacturers is different, it is difficult to popularize this method for the time being.

session-based upload progress monitoring feature (session.upload_progress) introduced in PHP 5.4 provides a server-side upload progress monitoring solution. After upgrading to PHP 5.4, you can upload the progress bar using only the native PHP and the front-end Javascript without installing the APC extension.

This new session.upload_progress feature of PHP 5.4 under 1 is described in detail below.

Principle introduction

When the browser uploads a file to the server, PHP will store the details of the file upload (such as upload time, upload progress, etc.) in session. Then, as the upload proceeds, the information in session is updated periodically. In this way, the browser can use Ajax to periodically request a server-side script, which returns the progress information in session; Javascript on the browser side can display/update the progress bar according to this information.

So, how is the file upload information stored? How do we access it? Let's explain it in detail below.

Some configuration items are introduced in PHP 5.4 (set in php. ini)


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"

Among them, enabled controls whether upload_progress function is turned on or not, and it is turned on by default; cleanup sets whether to clear the relevant information of session after the request for file uploading is submitted, and it is turned on by default.

prefix and name are used to set the variable/key name of the progress information stored in session. See below for detailed use of these two items.

freq and min_freq are used to set how often the server updates progress information. Setting these two items reasonably can reduce the burden on the server.

In the form of uploading files, you need to set an identifier for this upload, and use this identifier to refer to the progress information in the following procedures. Specifically, there needs to be a hidden input in the upload form, and its name attribute is the value of session.upload_progress. name in php. ini; Its value is 1 identifier defined by yourself. As follows:


<input type="hidden"
    name="<?php echo ini_get('session.upload_progress.name'); ?>"
    value="test" />

After receiving the form uploaded from the file, PHP will create a new key in the $_SESSION variable. The key name is a string obtained by connecting the value of session.upload_progress. prefix with the identifier you defined above, which can be obtained as follows:


$name = ini_get('session.upload_progress.name');
$key = ini_get('session.upload_progress.prefix') . $_POST[$name]; $_SESSION[$key]; // Here is the progress information of this file upload

The structure of the variable $_ SESSION [$key] is as follows:


$_SESSION["upload_progress_test"] = array(
 "start_time" => 1234567890,   // Start time
 "content_length" => 57343257, // POST Total data length requested
 "bytes_processed" => 453489,  // Length of data received
 "done" => false,              // Is the request complete true Indicates completion, false Not completed  // Information for a single file
 "files" => array(
  0 => array( ... ),
  // Same as 1 Multiple files can be included in the request
  1 => array( ... ),
 )
);

In this way, we can use content_length and bytes_processed to get the percentage of progress.

Program example

After the introduction of the principle, we will complete the implementation of a file upload progress bar based on PHP and Javascript.

Upload a form

First, let's write our upload form page index. php with the following code:


<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>

Notice the session.upload_progress. name hidden item in the form, with the value set to test. Only one file in the form is uploaded to input, and you can add more if necessary.

Special attention should be paid here to the target property of the form below 1, where the setting points to iframe in 1 current page. This is a key point. By setting the target property, the submitted page of the form will be displayed in iframe, thus avoiding the current page jump. Because we have to display the progress bar on the current page.

# progress This div is used to display the progress bar.

Don't forget to add session_start () at the beginning of index. php.

Handle uploaded files

The form's action points to upload. php, where we process the uploaded file and dump it to the current directory. There is no difference between this and the usual upload processing.


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 an progress. php file to read the progress information in session; Then we add the Javascript code to index. php, initiate an Ajax request to progress. php, and update the progress bar according to the progress information obtained.

The code for progress. php is 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 output 1 percentage of progress.

In index. php, we add the following code to the bottom of the page (jQuery is used here for simplicity):


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, then repeatedly call fetch_progress () to get the progress information, and update the progress bar until the file is uploaded, showing 'Done! '.

Done!

Complete code download: http://xiazai.ofstack.com/201410/tools/samples-master.rar

Matters needing attention

Location of input Tag

name is session. upload_progress. input Tag 1 for name must be placed in the file input < input type="file" / > In front of.

Cancel Upload

Cancel the current upload by setting $_SESSION [$key] ['cancel_upload'] = true. However, 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 called through setTimeout () to ensure that the next request is returned before the next. If you use setInterval (), you can't guarantee this point, which may lead to 'No Advance, No Backward' in the progress bar.


Related articles: