2010-12-28 21 views
2

Ich muss ein PHP-Skript schreiben, um potenziell große Dateien herunterladen. Die Datei, die ich hier berichte, funktioniert meistens gut. Wenn die Verbindung des Clients jedoch langsam ist, endet die Anforderung (mit dem Statuscode 200) in der Mitte des Herunterladens, aber nicht immer am selben Punkt und nicht zur selben Zeit. Ich habe versucht, einige php.ini-Variablen zu überschreiben (siehe die ersten Anweisungen), aber das Problem bleibt bestehen. Ich weiß nicht, ob es relevant ist, aber mein Hosting-Server ist SiteGround, und für einfache statische Dateianforderungen funktioniert der Download auch mit langsamen Verbindungen.Download große Datei mit PHP

Ich habe Forced downloading large file with php gefunden, aber ich habe die Antwort von Mario nicht verstanden. Ich bin neu in der Webprogrammierung.

Also hier ist mein Code.

<?php 
    ini_set('memory_limit','16M'); 
    ini_set('post_max_size', '30M'); 
    set_time_limit(0); 

    include ('../private/database_connection.php'); 


    $downloadFolder = '../download/'; 
    $fileName = $_POST['file']; 
    $filePath = $downloadFolder . $fileName; 
    if($fileName == NULL) 
    { 
     exit; 
    } 
    ob_start(); 
    session_start(); 


    if(!isset($_SESSION['Username'])) 
    { 
     // or redirect to login (remembering this download request) 
     $_SESSION['previousPage'] = 'download.php?file=' . $fileName; 
     header("Location: login.php"); 
     exit; 
    } 

    if (file_exists($filePath)) 
    {    
     header('Content-Description: File Transfer'); 
     header('Content-Type: application/octet-stream'); 
     //header('Content-Disposition: attachment; filename='.$fileName); 
     header("Content-Disposition: attachment; filename=\"$fileName\""); 
     header('Content-Transfer-Encoding: binary'); 
     header('Expires: 0'); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     //header('Pragma: public'); 
     header('Content-Length: ' . filesize($filePath)); 
     ob_clean(); 
     flush(); 

     // download 
     // 1 
//  readfile($filePath); 
     // 2 
     $file = @fopen($filePath,"rb"); 
     if ($file) { 
      while(!feof($file)) { 
      print(fread($file, 1024*8)); 
      flush(); 
      if (connection_status()!=0) { 
       @fclose($file); 
       die(); 
      } 
      } 
      @fclose($file); 
     } 
     exit; 
    } 
    else 
    { 
     header('HTTP/1.1 404 File not found'); 
     exit; 
    } 
?> 
+0

Werfen Sie einen Blick auf http://stackoverflow.com/questions/597159/sending-large-files-reliably-in-php, gibt es eine Antwort über die 'X-SENDFILE' Header. Überprüfen Sie jedoch, ob Ihr Host diese Kopfzeile unterstützt. – Joost

+0

Ich glaube nicht, dass es relevant ist, aber ich verwende ASIHTTPRequest-Bibliothek, um die Anfrage zu stellen. Ich baue einen ASIFormDataRequest und setze einen downloadDestinationPath. – dnaxxx

+0

Es scheint, dass x-sendfile nicht unterstützt wird, da die Antwort sofort eintrifft, mit Statuscode 200, aber ohne die Datei. Ich werde Siteground fragen, ob ich es aktivieren kann. – dnaxxx

Antwort

2

HTTP-Statuscode von 200 bedeutet, dass alles ordnungsgemäß ausgeführt wurde.

Überprüfen Sie, ob Ihre Inhaltslänge korrekt ist und versuchen Sie es ohne die Funktion connection_status(). Es meldet möglicherweise nicht ordnungsgemäß, dass der Benutzer die Verbindung getrennt hat. PHP hat eine connection_aborted() Funktion, die das sein kann, was Sie brauchen. Update: Weil Sie nach Mario's Antwort gefragt haben, bedeutet das, dass Sie Ihren Benutzer auf die tatsächliche Datei auf dem Server umleiten und Ihren Server damit umgehen lassen sollten, anstatt zu kopieren, was der Server bereits tun kann. Mit anderen Worten, Sie sollten header("Location: " . $filePath) oder eine Verknüpfung zum Dateipfad verwenden, anstatt Ihr Skript zu verwenden. Der Nachteil ist, dass Sie den Download des Anhangstils nicht verwenden können, aber Sie können ihn in einem neuen Fenster öffnen, das einen ähnlichen Effekt hat.

+0

sollten Sie Ihren Kommentar zu Ihrer Antwort hinzufügen. Ich bin fast sicher, dass was passiert, ist die Verbindung hat ein Bitflag gesetzt (zum Beispiel warten) und ist daher nicht mehr gleich der Zahl 0. Dann gebe ich Ihnen ein +1 für Ihre Antwort. – sholsinger

+0

Ich habe die Header der Antwort überprüft und die Inhaltslänge ist korrekt. Auch das Auskommentieren der gesamten if-Anweisung (die connection_status überprüft) ändert das Verhalten nicht. – dnaxxx

+0

Umleitung funktioniert nicht (gibt 404 zurück), da die Datei nicht öffentlich ist, denke ich. Vielleicht hat Mario in dem anderen Thema einen Workaround vorgeschlagen, aber das habe ich nicht verstanden. ... ich bin immer noch am Startpunkt. Vielleicht gibt es etwas Schlechtes mit meinem Gastgeber? – dnaxxx