2011-01-16 11 views
7

Próbuję wymusić pobieranie plików z mojego serwera za pomocą PHP. Nie jestem pro w PHP, ale po prostu nie mogę obejść problemu pobierania plików w rozmiarze 0 bajtów.PHP Force Pobierz Causing 0 Byte Files

KOD:

$filename = "FILENAME..."; 

header("Content-type: $type"); 
header("Content-Disposition: attachment;filename=$filename"); 
header("Content-Transfer-Encoding: binary"); 
header('Pragma: no-cache'); 
header('Expires: 0'); 
set_time_limit(0); 
readfile($file); 

Czy ktoś może pomóc? Dzięki.

+2

Czy jesteś pewien, że podany plik istnieje przy użyciu tej ścieżki i ma pewne treści? – Gumbo

+1

Po prostu mała uwaga, ale powinieneś uważać na przemierzanie katalogów. Potencjalny napastnik może na przykład użyć "../../../var/www/config.php" i może odczytać poufne dane. –

+0

dowolne rozwiązanie tego problemu, stojące przed tym samym problemem –

Odpowiedz

2

używam następujące metody w phunction i nie miałem żadnych problemów z nim do tej pory:

function Download($path, $speed = null) 
{ 
    if (is_file($path) === true) 
    { 
     $file = @fopen($path, 'rb'); 
     $speed = (isset($speed) === true) ? round($speed * 1024) : 524288; 

     if (is_resource($file) === true) 
     { 
      set_time_limit(0); 
      ignore_user_abort(false); 

      while (ob_get_level() > 0) 
      { 
       ob_end_clean(); 
      } 

      header('Expires: 0'); 
      header('Pragma: public'); 
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
      header('Content-Type: application/octet-stream'); 
      header('Content-Length: ' . sprintf('%u', filesize($path))); 
      header('Content-Disposition: attachment; filename="' . basename($path) . '"'); 
      header('Content-Transfer-Encoding: binary'); 

      while (feof($file) !== true) 
      { 
       echo fread($file, $speed); 

       while (ob_get_level() > 0) 
       { 
        ob_end_flush(); 
       } 

       flush(); 
       sleep(1); 
      } 

      fclose($file); 
     } 

     exit(); 
    } 

    return false; 
} 

Można spróbować po prostu robi:

Download('/path/to/file.ext'); 
+0

Przyjemna mała implementacja do dławienia :) – RobertPitt

+1

Dziękuję bardzo, ale wydawało się, że nie działa:/ – Alex

+0

Kto by to głosował? – RobertPitt

6

Nie jesteś sprawdzenie, czy plik istnieje. Spróbuj użyć tego:

$file = 'monkey.gif'; 

if (file_exists($file)) 
{ 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename='.basename($file)); 
    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($file)); 
    ob_clean(); 
    flush(); 
    readfile($file); 
    exit; 
}else 
{ 
    echo "File does not exists"; 
} 

Zobacz, co otrzymasz.

Należy również zauważyć, że zmusza to pobieranie jako strumień oktetowy, zwykły plik binarny. Niektóre przeglądarki będą mieć trudności ze zrozumieniem dokładnego typu pliku. Jeśli, na przykład, wysyłasz GIF z nagłówkiem Content-Type: application/octet-stream, przeglądarka może nie traktować go jak obraz GIF. Powinieneś dodać konkretne sprawdzenia, aby określić, jaki jest typ zawartości pliku i wysłać odpowiedni nagłówek Content-Type.

+0

Dzięki Robert, ale to nie działa:/ – Alex

+1

To działa, myślę, że musisz przedłużyć swoje pytanie, z której przeglądarki korzystasz, jaki jest plik, gdzie znajduje się jego lokalizacja, uprawnienia do pliku, a także katalog, i jaki serwer działa. – RobertPitt

+0

dzięki za to. Miałem problem z bajtem 0 tylko z plikami ppt. Ob_clean() i flush() przed stream_get_contents() pomogły. – pduersteler

2

Musisz określić Content-Length nagłówka:

header("Content-Length: " . filesize($filename)); 

Ponadto nie powinien wysłać Content-Transfer-Encoding nagłówek. Zarówno z HTTP/1.0 i HTTP/1.1 specs state, że "HTTP nie używa pola Content-Transfer-Encoding (CTE) w RFC 1521".

1

Ten problem jest taki sam jak mój projekt strony. Ten kod użyłem:

<?php 

$file = $_SERVER["DOCUMENT_ROOT"].'/.../.../'.$_GET['file']; 

if(!file) 
{ 
    // File doesn't exist, output error 
    die('file not found'); 
} 
else 
{ 

    //$file_extension = strtolower(substr(strrchr($file,"."),1)); 
    $file_extension = end(explode(".", $file)); 

    switch($fileExtension) 
    { 
    case "pdf": $ctype="application/pdf"; break; 
    case "exe": $ctype="application/octet-stream"; break; 
    case "zip": $ctype="application/zip"; break; 
    case "doc": $ctype="application/msword"; break; 
    case "xls": $ctype="application/vnd.ms-excel"; break; 
    case "ppt": $ctype="application/vnd.ms-powerpoint"; break; 
    case "gif": $ctype="image/gif"; break; 
    case "png": $ctype="image/png"; break; 
    case "jpeg": 
    case "jpg": $ctype="image/jpg"; break; 
    default: $ctype="application/force-download"; 
    } 

    nocache_headers(); 

    // Set headers 
    header("Pragma: public"); // required 
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
    header("Cache-Control: public"); // required for certain browsers 
    header("Content-Description: File Transfer"); 
    header("Content-Type: $ctype"); 
    header("Content-Disposition: attachment; filename=".$file.";"); 
    header("Content-Transfer-Encoding: binary"); 
    header("Content-Length: ".filesize($file)); 

    readfile($file); 
} 
?> 

Myślę, że problem jest na serwerze zachodzącego jak ustawienie PHP lub ustawienia pamięci podręcznej, ale nie mam żadnych pomysł, aby zrobić to moje zdanie.

1

Robię to, aby pobrać plik PDF ...

$filename = 'Application.pdf'; 
header("Content-Type: application/pdf"); 
header("Content-Disposition: attachment; filename=$filename"); 
echo $pdf; 

myślę brakuje ostatniego rzędu, w którym faktycznie wysłać zawartość pliku z co masz w $file.

Pablo

0

Plik otwarty ok dla mnie, kiedy zmieniono katalog do lokalizacji pliku.

0

Sztuką jest sprawdzenie za pomocą file_exists, aby potwierdzić poprawną ścieżkę. Duże zamieszanie polega na tym, że w przypadku ścieżek PHP nie trzeba zaczynać od "/", aby podać ścieżkę startową swojej witryny.

'/folder/file.ext' #bad, needs to know the real full path 

w php/jest już główną ścieżką do strony internetowej, nie trzeba o tym wspominać. Wystarczy:

'folder/file.ext' #relative to the/website 

ta będzie współpracować z file_exists, nagłówka pliku, readfile, etc ...