Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] wałek z downloadem
Forum PHP.pl > Forum > Przedszkole
daves
Witam,
Problem dotyczy błędnego pobierania plików za pomocą skryptu php tak więc nie chcesz czytać, irytuje Cię to - nie czytaj.

Napisałem skrypt, dzięki któremu pobieram pliki z serwera niejawnie. Czyli uruchamiam funkcję podając jej pewne argumenty, dzięki którym wyszukuję właściwy plik i wysyłam plik użytkownikowi do pobrania bla bla bla. Wałkowane od lat ale jakoś musiałem zacząć
Otóż, wszystko pięknie ładnie ale... w przypadku pobierania plików większych występuje błąd pobierania - pobiera mi plik o wielkości 195B mimo, że plik zajmuje 31MB - wydaje mnie się, że jest to jakiś nagłówek przekierowania czy coś takiego. Z plikami o wielkości do 16MB (tylko do 16 sprawdzałem) nie ma żadnego problemu. Klikam, pobieram, otwieram cyk działa.

Z grubsza skrypt wygląda tak:
  1. <?php
  2. $file_extension = strtolower(substr(strrchr($file,"."),1)); // rozszerzenie pliku
  3.     $typ_mime = DajTyp($file_extension); // zwracam nagłówek typu np. "application/octet-stream" lub "image/jpg"
  4.  
  5.  
  6. // NAGŁÓWKI HTTP
  7.     if (! is_file($file)) {  
  8.          header('HTTP/1.1 404 File Not Found');
  9.      die();
  10.     }
  11.            
  12.     header("Pragma: public");
  13.  
  14.     //ZOSTALO SPRAWDZONE Z CZESCIOWYM POBIERANIEM I BEZ
  15.     if ($range){
  16.          $reg = "/bytes=([0-9]+)-([0-9]*)/";
  17.      preg_match($reg, $range, $matches);
  18.  
  19.         $r_start     = (int) $matches[1];
  20.     $r_stop     = (int) $matches[2];
  21.     if ($r_stop < $r_start) $r_stop = $fsize - 1;
  22.     $c_length = $r_stop - $r_start + 1;
  23.  
  24.     header('HTTP/1.1 206 Partial Content');
  25.     header('Content-Range: bytes ' . $r_start . '-' . $r_stop . '/' . $fsize);
  26.     }else{            
  27.                  header('HTTP/1.1 200 OK');
  28.         }    
  29.  
  30.     // NAGŁÓWKI SPRAWDZILEM CHYBA W KAZDEJ WARIACJI - BEZ EFEKTU
  31.     header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  32.            
  33.     header('Content-Description: File Transfer');            
  34.     header("Content-Disposition: attachment; filename=".$file);
  35.     header('Accept-Ranges: bytes');
  36.            
  37.     header('Content-Type:'.$typ_mime);
  38.     header('Content-Transfer-Encoding: binary');
  39.     header('Content-Length: ' . filesize($file));
  40. ?>


sam proces pobierania sprawdziłem... i za pomocą funkcji FILEREAD() i za pomocą FREAD()
  1. <?php
  2. // ROZWIĄZANIE A
  3.     readfile($file);
  4.     exit;
  5. ?>


  1. <?php
  2. // ROZWIĄZANIE B
  3.     @readfile($file);
  4.     exit;
  5. ?>


  1. <?php
  2. // ROZWIĄZANIE C
  3.     if ($fp = fopen($file, 'rb'))
  4.    {
  5.             while (!feof($fp))
  6.            {
  7.                print fread($fp, 512 * 1024);
  8.            }
  9.            fclose($fp);
  10.    }
  11. ?>


  1. <?php
  2. // ROZWIĄZANIE C
  3.     if ($fp = fopen($file, 'rb'))
  4.    {
  5.             while (!feof($fp))
  6.            {
  7.                print fread($fp, 512 * 1024);
  8.                                usleep( 1 );
  9.            }
  10.            fclose($fp);
  11.    }
  12. ?>


W przypadku rozwiązania A i B plik 31MB nie jest pobierany (tylko 195B otrzymuje użytkownik). Rozwiązanie C i D rozbiłem celowo dla przedstawienia różnicy zastosowania funkcji usleep(x). Rozwiązanie C nie daje efektu pozytywnego. Dopiero rozwiązanie D może satysfakcjonować ale częściowo. Plik pobierany jest w przeglądarkach IE oraz OPERA - w przypadku FIREFOXA nie ma efektu.

Skrypt, który przedstawiłem został mocno okrojony w celu przedstawienia problemu i jest on efektem paru dni googlowania i przeglądania forum. Wiem, że problem poruszany już był masę razy, ale cóż... jeszcze nie znalazłem rozwiązania właściwego.

Chciałbym usłyszeć wasze solucje, złote myśli,
Dawid.

wolna myśl... a może to problem po stronie serwera, może to jakieś ograniczenie, które powoduje obcięcie bufora czytanego pliku . Serwer na superhost.pl.
Lejto
testujesz na localhoscie?
jeżeli nie to może na twoim servie jest limit wyczerpany albo coś tongue.gif
jak możesz to przetestuj na localu
daves
Tak, jasne. Zanim cokolwiek wrzucam na serwer robię na localu. Tutaj używam Krasnala. To jednak nie może być odniesienie do problemu gdyż już nie raz się przekonałem, że to co działa na serwerze na windowsie nie zawsze ma przełożenie na linucha przez chociażby inny interpreter plików lub konfigurację php.
dr_bonzo
Zobacz co zawiera ten pobrany plik z 100Bajtami, bycmoze komunikat bledu.
Lejto
i daj na początek skryptu error_reporting(E_ALL); i zobacz czy pokaże jakieś błędy
daves
Ściągnięty plik zawiera następującą treść błędu:
  1. Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 32997376 bytes) in /users/x on line y


Zrobiłem więc taki motyw. Jak już pisałem, zarówno IE jak i Opera ściągały plik prawidłowo (rozwiązanie D) a Firefox robił problem. Więc idąc tym tropem usunąłem wszystkie dane prywatne "Narzędzia -> Wyczyść dane prywatne". Po tej czynności uruchomiłem skrypt ponownie i ku mojemu zdziwieniu plik został ściągnięty prawidłowo.

Wróciłem zatem do rozwiązania A i użyłem funkcji readfile(); Uruchomiłem skrypt, który ponownie ściągnął mi błędne dane. Zmieniłem z powrotem w skrypcie odpowiednie linie na rozwiązanie D po czym puściłem skrypt ponownie i znów Firefox błędnie ściągnął plik z powyższym komunikatem. Zatem po raz kolejny użyłem czyszczenia danych prywatnych po czym puściłem skrypt raz jeszcze z rozwiązaniem D i.... ściągnął prawidłowo.



EDIT:

Dodając jeszcze 2 słowa na zakończenie, jak się okazuje Rozwiązanie D jest prawidłowe i ściąga pliki niezależnie od ich wielkości.
Powodem, dla którego download plików za pomocą Firefoxa był błędny jest jego specyfikacja. W przypadku ściągania po raz kolejny tego samego pliku za pomocą tego samego skryptu firefox w pierwszej kolejności szuka pliku i skryptu w katalogu danych tymczasowych.

Pzdr.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.