2013-06-28 7 views
5

Próbuję pobrać plik .mp4. (około 1,3 GB rozmiar). Używam następujący: Wymuszanie pobierania z pliku php

<?php 
$path = "video.mp4"; 
header('Accept-Ranges: bytes'); // For download resume 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename="'.basename($path).'"'); 
header('Content-Length: ' . filesize($path)); // File size 
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly 
header('Content-Type: application/octet-stream'); 
header('Expires: 0'); 
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT'); 
header('Pragma: no-cache'); 
ob_clean(); 
flush(); 
readfile($path); 

otwieram plik php i firefox wyskakuje z menu "chcesz zapisać". Rozmiar wygląda dobrze. Naciskam Zapisz jako, na moim pulpicie. Ostateczny pobrany plik, lista jako losowy rozmiar, około 400 MB (330, 463 i 440).

nagłówki odpowiedzi są:

Connection: Keep-Alive 
Content-Disposition: attachment; filename="//www.frederikspang.dk/elevgallavideo.mp4" 
Content-Length: 1422778850 
Content-Type: video/mp4 
Date: Sun, 30 Jun 2013 22:12:30 GMT 
Keep-Alive: timeout=10, max=50 
Pragma: public 
Server: Apache 
content-transfer-encoding: binary 
+1

Być może zbliżasz się do limitu czasu wykonania. Czy pobieranie zatrzymuje się zawsze po tym samym czasie? –

+0

Pobieranie pobranych plików trwa o wiele więcej niż to; więc powinieneś usunąć "Accept-Ranges". Zobacz: http://stackoverflow.com/questions/157318/resumable-downloads-when-using-php-to-send-the-file –

+0

Czy używasz buforowania wyjścia? Jeśli nie, prawdopodobnie nie potrzebujesz ob_clean() i flush(), ponieważ polecenie readfile wypisze dane bezpośrednio do klienta. – dethtron5000

Odpowiedz

0
<?php 
$filename = "theDownloadedFileIsCalledThis.mp4"; 
$myFile = "/absolute/path/to/my/file.mp4"; 

// Add bellow code for mime type 
$ext=strtolower(substr($fl,strrpos($myFile,"."))); 
$mime_types = array(
      '.txt' => 'text/plain', 
      '.htm' => 'text/html', 
      '.html' => 'text/html', 
      '.php' => 'text/html', 
      '.css' => 'text/css', 
      '.js' => 'application/javascript', 
      '.json' => 'application/json', 
      '.xml' => 'application/xml', 
      '.swf' => 'application/x-shockwave-flash', 
      '.flv' => 'video/x-flv', 

      // images 
      '.png' => 'image/png', 
      '.jpe' => 'image/jpeg', 
      '.jpeg' => 'image/jpeg', 
      '.jpg' => 'image/jpeg', 
      '.gif' => 'image/gif', 
      '.bmp' => 'image/bmp', 
      '.ico' => 'image/vnd.microsoft.icon', 
      '.tiff' => 'image/tiff', 
      '.tif' => 'image/tiff', 
      '.svg' => 'image/svg+xml', 
      '.svgz' => 'image/svg+xml', 

      // video 
      '.3gp' => 'video/3gpp', 
      '.3g2' => 'video/3g2', 
      '.avi' => 'video/avi', 
      '.mp4' => 'video/mp4', 
      '.asf' => 'video/asf', 
      '.mov' => 'video/quicktime', 
     ); 

if (array_key_exists($ext, $mime_types)){ 
    $mm_type=$mime_types[$ext]; 
}else{ 
    $mm_type="application/octet-stream"; 
} 
$mm_type="application/octet-stream"; 

header("Cache-Control: public, must-revalidate"); // Avoid this line 
header("Pragma: public"); // Add this line 
header("Pragma: hack"); // Avoid this line 
header("Content-Type: " . $mm_type); 
header("Content-Length: " .(string)(filesize($myFile))); // Avoid this line 
header('Content-Disposition: attachment; filename="'.$filename.'"'); 
header('Content-Length: ' . filesize($myFile)); // Add this line 
header("Content-Transfer-Encoding: binary\n"); 
ob_clean(); // Add this line 

readfile($myFile); 

?> 
+0

Bardzo niejasna odpowiedź. To nie jest dobrze udokumentowane. Proszę opracować "unikaj" i "dodawaj" i dlaczego. –

+0

odniesienie typów mime jest użyteczne, a deklaracje nagłówków mają sens ... "Unikaj" oczywiście oznacza "nie używaj", a "Dodaj" oznacza "dodaj". To, co mógł zrobić, dostarczyło lepszego wyjaśnienia, dlaczego – zgr024

+0

Co ze wszystkimi typami mime, jeśli chcesz ustawić '$ mm_type =" application/octet-stream "' anyways? –

1

to trudne - większość konfiguracji php nie powiedzie się po 30 sekundach. Jeśli posiadasz php.ini, możesz zmienić to na dłuższy limit. Ale wciąż - czy to nawet warto? Mam na myśli - pliki mogą się powiększyć lub sieć wolniej - i jeszcze raz trafisz w limit czasu.

Dlatego pobierających zostały wykonane - pobranie dużych plików na mniejsze kawałki Half Crazed pokazaliśmy wam kod że THIS odpowiedzi (jest nie tylko jeden - ten uwzględnia tylko jeden ze sposobów, klienci negocjować transfer - ale nadal ITS dobry start).

Na przykład Mega.co.nz korzysta z nowych funkcji html5. Pobiera plik w przeglądarce za pomocą porcji, dołączając plik do użytkownika, a następnie pobierając go z miejsca na dysku przeglądarki. Może wznowić pliki, wstrzymać pliki i tak dalej. (Niestety - bez kodu, ponieważ byłby dość duży i zawierałby więcej niż jeden język (php, js)).

PS: zmienić swoje readfile($path); do:

$handle=fopen($path, 'rb'); 
while (!feof($handle)) 
{ 
    echo fread($handle, 8192); 
    flush(); 
} 
fclose($handle); 

Ten plik nie zostanie załadowany do pamięci, CAŁY tylko części 8KiB na raz, a następnie wysłać je do użytkownika.

+0

Chociaż jest to bardzo prawdziwe - to było zachowanie na Apache2, które nie było wystarczająco wysokie. (Właśnie zobaczyłem to pytanie jeszcze raz, myślałem, że dam ci odpowiedź) –

+0

Przepraszamy za późną odpowiedź, ale keep-alive jest z innych powodów ... Większość serwerów po prostu zabije php po 60 sekundach - nawet jeśli nadal wysyła plik (byłby po prostu zabity). I podnoszenie tej granicy nie jest często mądre – Seti

Powiązane problemy