PHP uses Session to realize upload progress function

  • 2021-12-19 06:03:59
  • OfStack

In this paper, an example is given to show that PHP uses Session to realize the upload progress function. Share it for your reference, as follows:

The implementation of file upload progress bar basically depends on JS plug-in or File API of HTML5. In fact, PHP and ajax can also realize this function.

The PHP manual describes the upload progress of session as follows:

When session.upload_progress.enabled When the INI option is turned on, PHP can monitor the upload progress every time a file is uploaded. This information does not help the upload request itself, but the application can send an POST request to the terminal (e.g. via XHR) to check this status when the file is uploaded

When 1 upload is being processed, POST1 and INI are set at the same time session.upload_progress.name When the variable with the same name, the upload progress can be found in the $_SESSION Get in. When PHP detects such an POST request, it adds 1 set of data to $_ SESSION with an index of session.upload_progress.prefix And session.upload_progress.name The value connected from 1. Typically, these key values can be obtained by reading INI settings, such as


<?php
$key = ini_get("session.upload_progress.prefix") . ini_get("session.upload-progress.name");
var_dump($_SESSION[$key]);
?>

By setting the $_SESSION[$key]["cancel_upload"] Set to TRUE, and you can also cancel the upload of 1 file in process. When multiple files are uploaded in the same request, it cancels only the file uploads that are currently being processed and the file uploads that are not being processed, but does not remove those that have been completed. When an upload request is cancelled in this way, $_FILES error in will be set to UPLOAD_ERR_EXTENSION.

session.upload_progress.freq And session.upload_progress.min_freq The INI option controls how often upload progress information should be recalculated. By setting the values of these two options reasonably, the overhead of this function is almost negligible.

Note: In order for this to work properly, the request buffer of the web server needs to be disabled, otherwise PHP may receive file upload requests only when the file is fully uploaded. Programs known to buffer such large requests are Nginx.

The following principles are introduced:

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.

php. ini requires the following options to be configured


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 file upload request is submitted, which is turned on by default. If you need to debug $_ SESSION, it should be set to Off.
prefix and name are used to set the variable/key name of the progress information stored in session.
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:
The code is 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 concatenating the value of session.upload_progress. prefix with the above custom identifier, which can be obtained as follows:

The code is 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 
$_SESSION[$key] The structure of this variable is as follows: 

array (
  'upload_progress_test' => array (
    'start_time' => 1491494993,  //  Start time 
    'content_length' => 1410397, // POST Total data length requested 
    'bytes_processed' => 1410397, //  Length of data received 
    'done' => true,        //  Is the request complete  true Indicates completion, false Not completed 
    'files' => array (
      0 => array (
        'field_name' => 'file1',
        'name' => 'test.jpg',
        'tmp_name' => 'D:\\wamp\\tmp\\phpE181.tmp',
        'error' => 0,
        'done' => true,
        'start_time' => 1491494993,
        'bytes_processed' => 1410096,
      ),
    ),
  ),
);

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

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

Upload Form index. php


<?php session_start(); ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>PHP(5.4) Session  Upload progress  Demo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="keywords" content=""/>
  <meta name="description" content=""/>
  <meta name="author" content="">
  <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
  <style type="text/css">
    body{
      font-size:1em;
      color:#333;
      font-family: " Song Style ", Arial, sans-serif;
    }
    h1, h2, h3, h4, h5, h6{
      font-family: " Song Style ", Georgia, serif;
      color:#000;
      line-height:1.8em;
      margin:0;
    }
    h1{ font-size:1.8em; }
    #wrap{
      margin-top:15px;
      margin-bottom:50px;
      background:#fff;
      border-radius:5px;
      box-shadow:inset 0 0 3px #000,
      0 0 3px #eee;
    }
    #header{
      border-radius:5px 5px 0 0;
      box-shadow:inset 0 0 3px #000;
      padding:0 15px;
      color:#fff;
      background: #333333;
    }
    #header h1{
      color:#fff;
    }
    #article{
      padding:0 15px;
    }
    #footer{
      text-align:center;
      border-top:1px solid #ccc;
      border-radius:0 0 5px 5px;
    }
    .progress {
      width: 100%;
      border: 1px solid #4da8fe;
      border-radius: 40px;
      height: 20px;
      position: relative;
    }
    .progress .labels {
      position: relative;
      text-align: center;
    }
    .progress .bar {
      position: absolute;
      left: 0;
      top: 0;
      background: #4D90FE;
      height: 20px;
      line-height:20px;
      border-radius: 40px;
      min-width: 20px;
    }
    .report-file {
      display: block;
      position: relative;
      width: 120px;
      height: 28px;
      overflow: hidden;
      border: 1px solid #428bca;
      background: none repeat scroll 0 0 #428bca;
      color: #fff;
      cursor: pointer;
      text-align: center;
      float: left;
      margin-right:5px;
    }
    .report-file span {
      cursor: pointer;
      display: block;
      line-height: 28px;
    }
    .file-prew {
      cursor: pointer;
      position: absolute;
      top: 0;
      left:0;
      width: 120px;
      height: 30px;
      font-size: 100px;
      opacity: 0;
      filter: alpha(opacity=0);
    }
    .container{
      padding-left:0;
      padding-right:0;
      margin:0 auto;
    }
  </style>
</head>
<body>
<div id="wrap" class="container">
  <div id="header">
    <h1>Session Upload progress  Demo</h1>
  </div>
  <div id="article">
    <form id="upload-form" action="upload.php" method="POST" enctype="multipart/form-data" style="margin:15px 0"
       target="hidden_iframe">
      <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="test"/>
      <div class="report-file">
        <span> Upload a file … </span><input tabindex="3" size="3" name="file1" class="file-prew" type="file" onchange="document.getElementById('textName').value=this.value">
      </div>
      <input type="text" id="textName" style="height: 28px;border:1px solid #f1f1f1" />
      <p>
        <input type="submit" class="btn btn-default" value=" Upload "/>
      </p>
    </form>
    <div id="progress" class="progress" style="margin-bottom:15px;display:none;">
      <div class="bar" style="width:0%;"></div>
      <div class="labels">0%</div>
    </div>
  </div> <!-- #article -->
  <div id="footer">
    <p> </p>
  </div>
</div><!-- #wrap -->
<iframe id="hidden_iframe" name="hidden_iframe" src="about:blank" style="display:none;"></iframe>
<script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
  function fetch_progress() {
    $.get('progress.php', {'<?php echo ini_get("session.upload_progress.name"); ?>': 'test'}, function (data) {
      var progress = parseInt(data);
      $('#progress .labels').html(progress + '%');
      $('#progress .bar').css('width', progress + '%');
      if (progress < 100) {
        setTimeout('fetch_progress()', 500);
      } else {
        $('#progress .labels').html('100%');
      }
    }, 'html');
  }
  $('#upload-form').submit(function () {
    $('#progress').show();
    // The picture is relatively small, and the loading effect of the progress bar cannot be seen. The initial setting 33%
    $('#progress .labels').html('33%');
    $('#progress .bar').css('width', '33%');
    setTimeout('fetch_progress()', 500);
  });
</script>
</body>
</html>

Notice the session.upload_progress.name Hidden item with the value set to test. There is only one file in the form to upload to input, and you can add multiple files 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.

Upload file upload. php


<?php
/**
 *  Upload a file 
 */
if(is_uploaded_file($_FILES['file1']['tmp_name'])){
  //unlink($_FILES['file1']['tmp_name']);
  $fileName = 'pic_' . date('YmdHis') . mt_rand(10000,99999);
  $ext = substr($_FILES['file1']['name'], strrpos($_FILES['file1']['name'], '.'));
  move_uploaded_file($_FILES['file1']['tmp_name'], $fileName . $ext);
}

ajax Get Upload Progress progress. php


<?php
/**
 * AJAX Get the progress of uploading files 
 */
session_start();
$i = ini_get('session.upload_progress.name');
//session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
$key = ini_get("session.upload_progress.prefix") . $_GET[$i];
//session.upload_progress.prefix = "upload_progress_" . 'test'
if (!empty($_SESSION[$key])) {
  $current = $_SESSION[$key]["bytes_processed"]; //  Length of data received 
  $total  = $_SESSION[$key]["content_length"]; // POST Total data length requested 
  echo $current < $total ? ceil($current / $total * 100) : 100;
}else{
  echo 100;
}

Precautions:

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

2. By setting the $_SESSION[$key]['cancel_upload'] = true You can cancel the current upload. 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.

3. Should be adopted setTimeout() To call fetch_progress() This ensures that the next request will not begin until one request returns. If you use setInterval() You can't guarantee this point, which may lead to 'No Advance and Reverse' in the progress bar.

For more readers interested in PHP related contents, please check the topics on this site: "php File Operation Summary", "PHP Directory Operation Skills Summary", "PHP Common Traversal Algorithms and Skills Summary", "PHP Data Structure and Algorithm Tutorial", "php Programming Algorithms Summary" and "PHP Network Programming Skills Summary"

I hope this paper is helpful to everyone's PHP programming.


Related articles: