Framework Symfony – pobieranie plików zip.

13 01 2009

Bardzo często użytkownicy naszego serwisu mają mieć możliwość pobierania spakowanych plików .zip. Oczywiście najprostszym sposobem pobierania pliku jest udostępnienie na naszej stronie linków które odnoszą się do fizycznie zapisanych na serwerze plików .zip.

Np.: <a href=”katalog_plikow/plik.zip”>Pobierz plik</a>.

Ja będę chciał przybliżyć inny sposób pobierania takich plików. Napiszemy metodę w dowolnym module naszego projektu której zadaniem będzie „podanie” odwiedzającemu naszego pliku. Jakie zalety ma takie rozwiązanie:

  • możemy tworzyć statystyki dotyczące pobierania poszczególnych plików,
  • ukrywać fizyczną lokalizację danego pliku,
  • sprawdzać czy dany użytkownik ma prawo pobrać dany plik,
  • zmieniać nazwę.

Przypuśćmy, że w naszym projekcie napisanym przy użyciu frameworka symfony mamy moduł download, tzn

/htdocs/sf_sandbox/apps/frontend/module/download

Aplikacja „frontend” ponieważ dostęp będziemy chcieli ograniczyć tylko dla użytkowników tej aplikacji.

Następnie przechodzimy do edycji pliku actions.class.php w katalogu actions.

/htdocs/sf_sandbox/apps/frontend/module/download/actions/actions.class.php

Naszą metodę odpowiedzialną za pobieranie plików nazwijmy np.: pobierz

Metoda pobierz będzie udostępniała do pobrania pliki na podstawie ID pliku. Czyli wiemy, że w naszej bazie musimy mieć tabele która będzie zawierała informację o wszystkich naszych plikach do pobrania. Tabele ta nazwijmy np.: pliki i będzie miała najprostsza dla nas strukturę tzn:

  1.  
  2. <table name="pliki" phpName="Plik">
  3. <column name="plik_id" type="INTEGER" required="true" autoIncrement="true" primaryKey="true" />
  4. <column name="file_url" type="VARCHAR" size="255" required="true" />
  5. <column name="file_name" type="VARCHAR" size="255" required="true" />
  6. </table>

Gdzie:

  • plik_id – unikalne Id naszego pliku, na jego podstawie będziemy chcieli uzyskać dostęp do danego pliku
  • file_url – nazwa pod jaką zapisany jest fizycznie dany plik na serwerze
  • file_name – nazwa pod jaką użytkownik będzie zapisywał dany plik

Dostęp do danych uzyskamy na podstawie klasy PlikPeer

Tworząc strukturę tabeli pliki użyłem phpName=”Plik”, dlatego klasa do obsługi pojedynczego rekordu w tabeli pliki nazywa się Plik+Peer = PlikPeer.

Pomijam cały proces generowania struktury bazy danych, automatycznego generowania klas Peer itp. Moim celem jest pokazanie jak można oprogramować w symfony proces pobierania plików .zip. dlatego celowo nie będę się teraz (może kiedyś opisze z szczegółami) zajmował tymi wątkami.

Wróćmy do naszej metody pobierz.

  1.  
  2. public function executePobierz()
  3. {
  4. }

Mamy już jej szkielet, teraz musimy dopisać odpowiednie linie kodu.

  1. Pobieramy Id
  2. Na podstawie ID pobieramy interesujący nas rekord
  3. Sprawdzamy czy dany plik istnieje
  4. Udostępniamy do pobrania dany plik ustawiając odpowiednie nagłówki
  1.  
  2. public function executePobierz()
  3. {
  4. $id = $this->getRequestParameter(‘plik_id’);
  5. $plik = PlikPeer::retriveByPK($id);
  6. $response = $this->getResponse();
  7. $response->clearHttpHeaders();
  8. $file = sfConfig::get(’sf_web_dir’).‘/uploads/pliki/’.$plik->getFileUrl();
  9. if (!file_exists($file) || $plik->getFileUrl() == )
  10. {
  11. $this->forward404(‘File not found’);
  12. }
  13. $handle = fopen($file, "rb");
  14.  
  15. $this->content = fread($handle, filesize($file));
  16. fclose($handle);
  17. $filename = $plik->getFileName().‘.zip’;
  18. $response->setHttpHeader(‘Content-Disposition’, ‘attachment; filename="’.$filename.‘"’);
  19. $response->setHttpHeader(‘Content-length’, filesize($file));
  20. $response->setHttpHeader(‘Pragma’, ‘public’);
  21. $response->setHttpHeader(‘Content-Type’, ‘application/zip’);
  22. return sfView::SUCCESS;
  23. }

Oczywiście powyższy kod nie jest doskonały, można go zdecydowanie ulepszyć poprzez sprawdzanie istnienia wszystkich zmiennych, walidację nazwy pliku pobranego w $plik->getFileName(). Można zablokować pobieranie dla nie zalogowanych użytkowników itp.

Teraz jeszcze musimy ustawić widok dla naszej metody. W tym celu w katalogu templates tworzymy plik o nazwie PobierzSuccess.php.

/htdocs/sf_sandbox/apps/frontend/module/download/templates/PobierzSuccess.php

W pliku tym piszemy tylko jedną linie kodu :

  1.  
  2. <?php echo $content ?>

Do tego momentu każdy link na stronie, który będzie prowadził do modułu „download” a następnie do metody executePobierz pozwoli nam pobrać plik zip. Oczywiście należy pamiętać iż należy przekazać odpowiednie dane – id pliku, i ten plik musi istnieć.

Mamy już kod który pozwala nam pobrać pliki zip. Pobieranie powinno działać i na naszym dysku mamy już pobrany plik zip.

Plik istnieje ale czy możemy go rozpakować?
 

Uszkodzone archiwum zip.


Opcje

Info

Odpowiedz

Możesz używać tagów : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>