czwartek, 2 kwietnia 2015

Drupal: pobieranie plików przez PHP

Dziś szybki post o programowym pobieraniu plików w module CMS Drupal. Od razu dodam, że nie chodzi o plik przechowywany z pomocą File API. O ile File API jest fajne, o tyle do zarządzania plikami generowanymi przez Cron wolałem go nie używać.


Zamieszczony poniżej kod może być użyty do pobrania dowolnego pliku, dlatego warto zadbać o jego odpowiednie zabezpieczenie. Przecież nie chcemy aby przypadkiem ktoś zaczął pobierać kod naszego własnego modułu.
header('Cache-Control: public');
header('Content-Type: application/octet-stream');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0');
header('Content-Disposition: attachment; filename="' . $Filename . '";');
header('Content-Length: ' . filesize($path));
header('Content-Transfer-Encoding: binary');

if (ob_get_level()) {
 ob_end_clean();
}

if ($fd = fopen($path, 'rb')) {
 while (!feof($fd)) {
  print fread($fd, 1024);
 }
 fclose($fd);
} else {
 drupal_not_found();
}

drupal_exit();

Bardzo istotne okazało się ustawienie nagłówka Content-Length. Bez tego nagłówka, transfer pliku wykłada się w losowych momentach i przesłanie czegoś powyżej 40MB graniczyło z cudem. Ciekawa jest jeszcze inna sprawa. Pierwotnie chciałem użyć funkcji readfile(). Pomimo wyłączenia buforowania wyjścia, skrypt wykładał się z błędem informującym o braku pamięci (limit 120MB, plik 150MB). Teoretycznie pod spodem PHP robi dokładnie to samo co ja, czyli czyta plik w pętli porcjami wysyłając go do użytkownika. Teoria teorią, a praktyka wymusiła jawne czytanie pliku po 1024B.

Brak komentarzy:

Prześlij komentarz