Web application: any way to monitor HTTP files

I am working on a web application. This will allow users to download files from the server via the HTTP protocol. Files can be up to 4 GB in size.

These are my requirements and limitations:

  • Passing an HTTP file in%
  • Register when an HTTP file download completes
  • Register if an HTTP file upload error
  • Register if user canceled download
  • Continue to download the incomplete file.
  • To be able to upload files up to 4 GB
  • Only JavaScript / HTML5 on the client side and PHP on the server should be implemented.
  • May not be implemented in Java or Flash on the client side.

My development environment:

  • Apache
  • Php
  • MySQL
  • Windows 7

, , , PHP script, , ( , , ). PHP connection_aborted() 50% .

, - ? - NGINX LIGHTTPD? LUA Perl Apache, PHP?

My Current Download Script:

    while(!feof($fileObject))
    {
        usleep(100000);

        //print(@fread($fileObject, $chunkSize));
        echo(@fread($fileObject, $chunkSize));

        // gradually output buffer to avoid memory problems by downloading large files
        ob_flush();
        flush();

        // check if the client was disconnected
        // important for cancelled or interrupted downloads
        if (Connection_Aborted())
        {

            // sent to the database that the connection has been aborted
            $result = mysqli_query($dbc, "UPDATE current_downloads SET connection_aborted=TRUE WHERE user_id=1;");

            // close the database connection
            mysqli_close($dbc);

            // close the open file
            @fclose($fileObject);

            exit(json_encode(array("result" => false, "error" => "Connection with the client was aborted.")));
        }

        $nLoopCounter++;
        $transferred += $chunkSize;
        $downloadPercentage = (($nLoopCounter * $chunkSize) / $fileSize) * 100;

        $result = mysqli_query($dbc, "UPDATE current_downloads SET progress_percent=$downloadPercentage, transferred=$transferred, connection_aborted=$strConnectionAborted, iteration=$nLoopCounter WHERE user_id=1;");
        if($result == false)
        {
            // close the database connection
            mysqli_close($dbc);

            // close the file
            fclose($handle);

            // prepare output message
            $outputArray = array("result" => 0, "message" => "Error Processing Database Query");

            // output the message
            echo json_encode($outputArray);
            exit;
        }
    }

.

+3
4

, PHP, - Boost.Asio SAPI, Facebook, , github .

, , Apache -, SAPI (Fast-CGI, PHP-FPM, mod_apache ..) PHP. , , , ( , -, SAPI, PHP ..).

( ) , PHP Apache -. PHP sapi, PHP , . , PHP -, .

PHP-, PHP . PHP , , , , async.

Boost.Asio tidbits PHP, , , . . .

+2

, , ( , 100% ) (. "" ):

, , % -Value, script . , , PHP , .

, :

download.php, . javascript, , (.. download.php?fileId=5&chunk=59). Javascript , , .

, Javascript , : , " ". , , .

- , ( - ), . JavaScript, ( ) , php/Javascript. ( Javascript, , , .)


, :

, , :

  • .
  • "" .
  • .

, / .

a download.php, . ChunkSize "10", ( → )

<?

header('Cache-Control: max-age=31556926');
$etag = 'a_unique_version_string';
header('ETag: "'.$etag.'"');

$chunkCount = 10;

$file = $_GET["file"]; //ignored in this example
$file = "someImage.jpg";
$chunk = $_GET["chunk"];

$fileSize = filesize($file);
$chunkSize = ceil($fileSize / $chunkCount); //round to whole numbers.

//get required chunk.
$handle = fopen($file, "r");
$start = ($chunk-1) * $chunkSize + ($chunk-1);
$toRead = min($chunkSize+1, $fileSize - $start); //read next chunk or until EOF.
$end = $start + $toRead;

//echo "reading $toRead from $start to $end";
//die();

if (fseek($handle, $start) == 0){
  $c = fread($handle, $toRead); 
  echo $c;
  @fclose($handle);
}else{
  //error seeking: handle it.
}

?>

, URL- ( ) :

downloading http://dog-net.org/dltest/download.php?file=1&chunk=1
downloading http://dog-net.org/dltest/download.php?file=1&chunk=2
downloading http://dog-net.org/dltest/download.php?file=1&chunk=3
downloading http://dog-net.org/dltest/download.php?file=1&chunk=4
downloading http://dog-net.org/dltest/download.php?file=1&chunk=5

, JavaScript . . " ". , . : , , ,

<html>
  <head>   
    <script language="javascript">
      var urls = new Array();
      urls[0] = "http://dog-net.org/dltest/download.php?file=1&chunk=1";
      urls[1] = "http://dog-net.org/dltest/download.php?file=1&chunk=2";
      urls[2] = "http://dog-net.org/dltest/download.php?file=1&chunk=3";
      urls[3] = "http://dog-net.org/dltest/download.php?file=1&chunk=4";
      urls[4] = "http://dog-net.org/dltest/download.php?file=1&chunk=5";
      urls[5] = "http://dog-net.org/dltest/download.php?file=1&chunk=6";
      urls[6] = "http://dog-net.org/dltest/download.php?file=1&chunk=7";
      urls[7] = "http://dog-net.org/dltest/download.php?file=1&chunk=8";
      urls[8] = "http://dog-net.org/dltest/download.php?file=1&chunk=9";
      urls[9] = "http://dog-net.org/dltest/download.php?file=1&chunk=10";

      var fileContent = new Array();


      function downloadChunk(chunk){
        var url = urls[chunk-1];
        console.log("downloading " + url);
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.responseType = 'blob';
        xhr.onload = function (e) {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              document.getElementById("log").innerHTML += "downloading " + url + "<br />";
              fileContent.push(xhr.response); 
              document.getElementById("percentage").innerHTML = chunk / urls.length * 100;

              if (chunk < urls.length){  
                downloadChunk(chunk+1);
              }else{
                finishFile();
              }
            } else {
              console.error(xhr.statusText);
            }
          }
        };
        xhr.onerror = function (e) {
          console.error(xhr.statusText);
        };
        xhr.send(null);
      }

      function finishFile(){
         contentType = 'image/jpg'; //TODO: has to be set accordingly!
         console.log("Generating file");
         var a = document.createElement('a');
         var blob = new Blob(fileContent, {'type':contentType, 'endings':'native'});

         console.log("File generated. size: " + blob.size);

         //Firefox
         if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
            var url = window.URL.createObjectURL(blob);
            window.location = url;   
         }

         //IE 11 or chrome?
         if (!(window.ActiveXObject) && "ActiveXObject"){   
           //Chrome:
           if (window.chrome){
             a.href = window.URL.createObjectURL(blob);
             a.download = "download";  
             a.click();
           }else{
            //ie 11
            window.navigator.msSaveOrOpenBlob(blob, 'download');
          } 
         }
      } 


      function setProgress(chunk){
        document.getElementById("percentage").innerHTML = chunk / urls.length * 100;
      }
    </script>
  </head>
  <body onload="downloadChunk(1);">

  <div id="percentage"></div>
  <div id="log"></div>

  </body>
</html>

, Blobs - ... IE 11, Chrome 32 Firefox 27. Safari. .


: http://dog-net.org/dltest/ ( png-, paint/irfranview/whatevs - .)

. Second Call , , ( ) . ( "Forever" - , 7 !)


:

  • JavaScript ( )
  • finalFile- .
  • . ( 30 ).
  • Mime-Type .
  • .
  • , .

, , .

/Java/Silverlight, , !

+3

WebSockets HTML5.

( JavaScript), API .

( PHP), WebSocket.

, , , .

- , , , .

+1

, PHP ( , ) , , . , , , . , , , - Java Flash. , , ( , Java Flash , - ?).

.

You can still learn a little about ignore_user_abortand connection_aborted. I could somehow customize what you need. But you will not get really efficient and accurate enough to keep track of whether the download is really complete.

0
source

All Articles