Upload plików

Formularz HTML

Dzięki PHP możemy w łatwy i przyjemny sposób obsłużyć pliki uploadowane na serwer.
Jednak, by prawidłowo wysłać plik, niezbędny będzie odpowiedni formularz HTML.

Konstrukcja formularza musi spełniać następujące warunki:

  • Pierwszym z nich jest dodatkowy atrybut enctype=”multipart/form-data”, który musimy dodać, by móc wysłać plik.
  • Formularz MUSI być wysyłany wyłacznie metodą POST
  • Do formularza dodajemy ukryte pole o nazwie MAX_FILE_SIZE, które zawiera maksymalny rozmiar przesyłanego pliku podany w bajtach.
    Przykład dla pliku max 512kB:
    <input type="hidden" name="MAX_FILE_SIZE" value="512000">
  • Zasadniczy element to pole typu file, które umożliwia wybranie pliku z komputera użytkownika:
    <input type="file" name="plik">
  • Ostatnim, koniecznym elementem jest przycisk wysyłający formularz
    <input type="submit" name="wyslij" value="Wyślij formularz">

Przykładowy formularz zakładania konta z możliwością dodania awatara użytkownika może przedstawiać się następująco:
(w ramkach umieszczono elementy charakterystyczne dla formularza z wysyłaniem plików) formularz wysyłania pliku

Skrypt PHP na serwerze

Po wysłaniu pliku na serwer, w zmiennej superglobalnej $_FILES pojawia się nowy rekord $_FILES['plik'].
Zawiera on tablicę informacji o wysłanym pliku.
Te informacje to:

  • rozmiar - $_FILES['plik']['size']
  • nazwa - $_FILES['plik']['name'] (oryginalna nazwa pliku)
  • nazwa tymczasowa - $_FILES['plik']['tmp_name'] (generowana jest unikatowa nazwa z rozszerzeniem tmp, plik umieszczany jest w systemowym katalogu tymczasowym
  • błedy - $_FILES['plik']['error']
    Jeśli operacje przebiegły poptawnie pole to zawiera wartość 0.
    W przeciwnym wypadku znaczenie poszczególnych kodów jest następujące:
    1. - rozmiar pliku jest większy niż domyślny maksymalny, podany w pliku konfiguracyjnym (php.ini)
    2. - rozmiar pliku jest większy niż wartość pola formularza MAX_FILE_SIZE
    3. - plik nie został wysłany w całości
    4. - plik nie został wysłany
  • typ pliku - $_FILES['plik']['type']
    Pełna lista dostępnych typów plików znajduje się pod adresem:
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
    Chcąc sprawdzić, czy przesłany plik jest grafiką JPG wykonujemy instrukcję:
    
                    function test() {    
                        if ($_FILES['plik']['type'] != 'image/jpeg') {
                            echo "To nie jest grafika JPG";
                            return false;
                        }
                        return true;
                    }    
                    
Tak więc, po umieszczeniu na stronie odpowiedniego kodu, możemy sprawdzić z jakim plikiem mamy do czynienia.
Jeśli spełnia wszystkie nasze założenia możemy skopiować do katalogu docelowego.

Funkcje obsługujące upload plików

  •  bool is_uploaded_file(string nazwa_pliku) - funkcja sprawdza, czy pracujemy na pliku dopiero co wysłanym na serwer.

    Funkcja zwraca TRUE jeśli plik o nazwie nazwa_pliku został przysłany (upload) przez HTTP POST.
    To pomaga upewnić się, czy złośliwy użytkownik nie próbuje oszukać skryptu pracującego na plikach, tak aby działał on na plikach, na których nie powinien -- na przykład /etc/passwd.

    Ten rodzaj testów jest szczególnie ważny jeśli istnieje szansa, że cokolwiek robimy z przysłanymi plikami może zdradzić ich treść użytkownikowi lub nawet innym użytkownikom tego samego systemu.

    Do prawidłowego działania, funkcja is_uploaded_file() wymaga argumentu jak $_FILES['plik']['tmp_name']
    (tymczasowa nazwa i lokaliczaja pliku).
    Podanie oryginalnej nazwy przysyłanego pliku z komputera klienta $_FILES['plik']['name'] nie zadziała.

  •  bool move_uploaded_file($zrodlo, $cel) - funkcja przenosi z lokalizacji tymczasowej $zrodlo do lokalizacji docelowej $cel.

    Plik można przenieść pod nazwą oryginalną, jednak pamiętać należy, że kilku użytkowników może przesłać pliki pod takimi samymi nazwami.
    Spowoduje to nadpisanie istniejących plików bez informacji ze strony systemu.
    Musimy zadbać o to, aby nazwy plików nie pokrywały się.

    Przykład procedury kopiującej pliki:

    
        $cel = "./pliki/".rand(1000,9999).$_FILES['plik']['name'];
    
        if(!move_uploaded_file($_FILES['plik']['tmp_name'], $cel)) {
            echo "Nie udało się skopiować pliku do katalogu."; 
        }
    

    Zastosowana została tutaj funkcja rand(1000,9999), która generuje losową liczbę z przedziału 1000...9999 i umieszcza ją przed oryginalną nazwą pliku.

Projekt i wykonanie: Ryszard Rogacz© 1999−2024