【问题标题】:Get bytes transferred using PHP5 for POST request获取使用 PHP5 为 POST 请求传输的字节
【发布时间】:2017-07-16 23:08:21
【问题描述】:

注意我是 PHP、Apache 和服务器编程的新手,希望能提供更全面的解释。


上下文

我在 javascript 中创建了一个在上传文件时显示的进度条。当前,我以设定的帧速率更新进度条(看看它是否有效)。

显然,为了使这个进度条准确,所有内容都应与传输的字节数与总字节数相比。

问题

使用 PHP5 如何获取与文件总字节数相关的传输字节数的信息,以便我可以将其传递给 JS 函数 updateProgress(bytesSoFar, totalBytes) 以更新我的进度条?请详细指导我完成以下代码所需的修改以使其正常工作。我看过xhr 的例子,但它们并不能完全访问。

我刚刚设置了 LocalHost 并正在使用 W3Schools 的 PHP File Upload 教程。为了使模拟的“上传”正常工作,我按照此 S.O. 中的建议更改了本地权限。 post。我不一定需要读取文件,我只想知道已经传输了多少字节。


代码

目前我有两个文件:

  • index.php

  • 上传.php

index.php

<!DOCTYPE html>
<html>
<body>

<form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>

</body>
</html>

上传.php

<?php
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) {
        echo "File is an image - " . $check["mime"] . ".";
        $uploadOk = 1;
    } else {
        echo "File is not an image.";
        $uploadOk = 0;
    }
}
// Check if file already exists
if (file_exists($target_file)) {
    echo "Sorry, file already exists.";
    $uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "Sorry, your file is too large.";
    $uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
    echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
    $uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
    echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
        echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}
?>

更新

我找到了这段代码:

test.php

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST" && !empty($_FILES["userfile"])) {



  // move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)
move_uploaded_file($_FILES["userfile"]["tmp_name"], "uploads/" . $_FILES["userfile"]["name"]);
}
?>
<html>
<head>
  <title>File Upload Progress Bar</title>
  <style type="text/css">
    #bar_blank {
    border: solid 1px #000;
    height: 20px;
    width: 300px;
    }

    #bar_color {
    background-color: #006666;
    height: 20px;
    width: 0px;
    }

    #bar_blank, #hidden_iframe {
    display: none;
    }
  </style>
</head>
<body>

  <div id="bar_blank">
    <div id="bar_color"></div>
  </div>
  <div id="status"></div>

  <form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="POST" id="myForm" enctype="multipart/form-data" target="hidden_iframe">
    <input type="hidden" value="myForm" name="<?php echo ini_get("session.upload_progress.name"); ?>">
    <input type="file" name="userfile"><br>
    <input type="submit" value="Start Upload">
  </form>

  <script type="text/javascript">
    function toggleBarVisibility() {
      var e = document.getElementById("bar_blank");
      e.style.display = (e.style.display == "block") ? "none" : "block";
    }

    function createRequestObject() {
      var http;
      if (navigator.appName == "Microsoft Internet Explorer") {
        http = new ActiveXObject("Microsoft.XMLHTTP");
      }
      else {
        http = new XMLHttpRequest();
      }
      return http;
    }

    function sendRequest() {
      var http = createRequestObject();
      http.open("GET", "progress.php");
      http.onreadystatechange = function () { handleResponse(http); };
      http.send(null);
    }

    function handleResponse(http) {
      var response;
      if (http.readyState == 4) {
        response = http.responseText;

        document.getElementById("bar_color").style.width = response + "%";
        document.getElementById("status").innerHTML = response + "%";

        if (response < 100) {
          setTimeout("sendRequest()", 1000);
        }
        else {
          toggleBarVisibility();
          document.getElementById("status").innerHTML = "Done.";
        }
      }
    }

    function startUpload() {
      toggleBarVisibility();
      setTimeout("sendRequest()", 1000);
    }

    (function () {
      document.getElementById("myForm").onsubmit = startUpload;
    })();
  </script>
</body>
</html>

progress.php

session_start();

$key = ini_get("session.upload_progress.prefix") . "myForm";
if (!empty($_SESSION[$key])) {
  $current = $_SESSION[$key]["bytes_processed"];
  $total = $_SESSION[$key]["content_length"];
  echo $current < $total ? ceil($current / $total * 100) : 100;

  $message = ceil($current / $total * 100) : 100;

  $message = "$message"
  echo "<script type='text/javascript'>alert('$message');</script>";
}
else {
  echo 100;
}
?>

与我之前的代码一样,它传输文件。但是,这直到最后才显示字节(即使它应该对此发出警报),它也会打开一个带有“完成”的新窗口。上一个窗口中的声明。

【问题讨论】:

标签: javascript php post http-post


【解决方案1】:

您可以使用Session Upload Progress 功能。它是原生的,但需要一些 php.ini 配置。

请看一下PHP manual

更新 1

注意,您不需要更改您的upload.php。您可以创建一个新的 php 文件(例如 progress.php)并向他们发出请求以检查您的 JS 的上传进度。

progress.php

<?php
$upload_id = $_GET['upload_id];
print json_encode($_SESSION['upload_progress_'.$upload_id]);

然后您的 JS 将向progress.php?upload_id=YourIdValue 发出 GET 请求,您将收到包含所有进度信息的 JSON。

【讨论】:

  • 感谢您提请我注意。有几件事:链接是相同的;它在该页面上清楚地说明您提供的方法表明它可能无法在上传完成之前获取该信息;而且没有完整的例子。
  • 我不知道您是否收到通知,我更新了答案以提供更多信息。如果没有,请再看一遍。
  • 对不起,这没有意义。如果我制作一个独立的文件,那么将永远不会调用该代码。所以即使上面的代码确实有效,它也不会在上下文中。
  • PHP 在 SESSION 变量中存储和更新所有上传进度信息。当您在表单中设置&lt;input type="hidden" name="&lt;?php echo ini_get("session.upload_progress.name"); ?&gt;" value="123" /&gt; 时,所有魔法都会发生。如果 PHP 接收到这个信息,它会将所有上传信息传递给这个会话变量。当您定义了一个会话时,它将可用于所有请求,直到会话结束或您将其销毁。如果您愿意,请查看PHP Sessions 文档以了解更多信息。
【解决方案2】:

您可以查看此Php File Upload Progress Bar,如果您坚持使用 Php 显示进度,它可能会帮助您入门。这使用 PECL 扩展 APC 来获取上传的文件进度详细信息。可以使用响应来计算服务器接收到的字节数 apc_fetch() 根据第一个链接。

另一个有趣的Track Upload Progress 教程,它使用了 PHP 的原生 Session Upload Progress 功能。

最后,如果您对使用 Javascript(或 JS 库)有点开放,那将是理想。我知道的一个易于使用、易于设置、众所周知且维护的库是FineUploader

【讨论】:

  • 嘿,谢谢你的链接,但我在赏金中指定我正在寻找关于你选择的方法如何工作的详细解释。您的第一个链接不显示进度条(并且查看代码似乎只是使用间隔计时器而不是获取字节)。第三个链接声明PHP may see the file upload only once fully uploaded(正如我已经指出的那样),第四个似乎很有用 - 但它的文档是卷积的 - 并且超出了 PHP 的范围。第二个链接分享了第三个链接的缺陷。
  • 更新了答案。另外,回答您的 cmets,是的,它确实使用了一个计时器(每 500 毫秒 ping 服务器并获取上传的文件详细信息) 提供的链接确实有效,请尝试上传一个更大的文件以查看进度条。如果您选择上传较小的文件,请减少计时器间隔以确保您的进度条相应更新。
  • PHP may see the file upload only once fully uploaded 看起来你错过了句子的前半部分。它说The web server's request buffering has to be disabled otherwise PHP may see the .... 如果你选择使用这个选项,你应该禁用请求缓冲。最后,关于 FineUploader 的documentationexamples,我认为它们肯定很容易理解。 (但正如答案中已经说明的那样,这是一个基于 JS 的解决方案)恕我直言,最好使用 JS。
猜你喜欢
  • 2018-09-25
  • 1970-01-01
  • 2011-09-19
  • 2016-06-19
  • 1970-01-01
  • 2018-05-17
  • 2012-07-06
  • 2016-07-11
  • 1970-01-01
相关资源
最近更新 更多