Logo

PHP - Obsługa plików

Opis: Zostanie omówiona obsługa plików w języku PHP, w tym mechanizmy otwierania, odczytu, zapisu i zamykania plików z wykorzystaniem funkcji fopen, fread, fwrite i fclose, a także przesyłanie plików na serwer przy użyciu tablicy $_FILES, umożliwiające efektywne zarządzanie danymi oraz obsługę plików użytkownika w aplikacjach webowych.

Zapis do pliku

PHP umożliwia pracę z plikami na serwerze, co jest niezbędne przy zapisywaniu danych, generowaniu logów czy obsłudze plików użytkownika. Do podstawowych operacji należą: otwieranie plików (fopen), odczyt (fread), zapis (fwrite) oraz zamykanie plików (fclose). Każda operacja odbywa się na tzw. uchwycie pliku (file handle), który reprezentuje otwarty plik w pamięci.

Dodatkowo PHP pozwala na przesyłanie plików z poziomu formularza HTML przy użyciu superglobalnej tablicy $_FILES. Mechanizm ten umożliwia odbiór pliku na serwerze, jego walidację (np. rozmiar, typ) oraz zapis w wybranej lokalizacji.

Operacje na plikach

Przykład: zapis i odczyt pliku

<?php
$plik = fopen("dane.txt", "w"); // otwarcie pliku w trybie zapisu
fwrite($plik, "Witaj świecie!\n"); // zapis danych do pliku
fclose($plik); // zamknięcie pliku

$plik = fopen("dane.txt", "r"); // otwarcie pliku w trybie odczytu
$tresc = fread($plik, filesize("dane.txt")); // odczyt zawartości
fclose($plik); // zamknięcie pliku

echo $tresc;
?>

Wyjaśnienie działania:

  • fopen("dane.txt", "w") - otwiera plik do zapisu (jeśli nie istnieje, zostanie utworzony; jeśli istnieje, zostanie nadpisany)

  • fwrite() - zapisuje tekst do pliku

  • fclose() - zamyka plik i zwalnia zasoby

  • fopen("dane.txt", "r") - otwiera plik w trybie odczytu

  • fread() - odczytuje określoną liczbę bajtów (tu: cały plik)

  • filesize() - zwraca rozmiar pliku w bajtach

  • echo - wyświetla zawartość pliku w przeglądarce

Zabezpieczenie operacji na plikach

Przykład: bezpieczny odczyt pliku

<?php
$sciezka = "dane.txt";

if (file_exists($sciezka)) {
    $plik = fopen($sciezka, "r");

    if ($plik) {
        $tresc = fread($plik, filesize($sciezka));
        fclose($plik);
        echo htmlspecialchars($tresc);
    } else {
        echo "Nie udało się otworzyć pliku.";
    }
} else {
    echo "Plik nie istnieje.";
}
?>

Zabezpieczenia:

  • file_exists() - sprawdza, czy plik istnieje (unikamy błędu)

  • sprawdzenie fopen() - upewniamy się, że plik się otworzył w warunku if

  • htmlspecialchars() - zabezpiecza przed wstrzyknięciem HTML/JS (XSS)

Przykład: zapis danych od użytkownika

<?php
if (isset($_POST["tekst"])) {
    $tekst = trim($_POST["tekst"]);

    if (!empty($tekst)) {
        $plik = fopen("dane.txt", "a"); // tryb dopisywania

        if ($plik) {
            fwrite($plik, $tekst . "\n");
            fclose($plik);
            echo "Zapisano dane.";
        } else {
            echo "Błąd zapisu.";
        }
    } else {
        echo "Pole jest puste.";
    }
}
?>

Zabezpieczenia:

  • trim() - usuwać białe znaki (takie jak spacje, tabulacje \t, nowe linie \n, powroty karetki \r) lub inne zdefiniowane znaki z początku i końca ciągu znaków (stringa).

  • empty() - sprawdza, czy dane nie są puste

  • tryb "a" - zapobiega nadpisaniu pliku. Włączenie trybu dopisywania do pliku.

Upload plików ($_FILES)

Przykład: przesyłanie pliku na serwer

Formularz HTML:

<form action="upload.php" method="post" enctype="multipart/form-data">
    Wybierz plik:
    <input type="file" name="plik">
    <input type="submit" value="Wyślij">
</form>

Plik upload.php:

<?php
if (isset($_FILES["plik"])) {
    $nazwa = $_FILES["plik"]["name"];
    $tymczasowy = $_FILES["plik"]["tmp_name"];

    move_uploaded_file($tymczasowy, "uploads/" . $nazwa);

    echo "Plik został przesłany.";
}
?>

Wyjaśnienie działania:

  • enctype="multipart/form-data" - enctype (encoding type) określa sposób kodowania danych formularza przed wysłaniem do serwera. multipart/form-data powoduje, że dane formularza są dzielone na części (multipart), każda część (np. pole tekstowe, plik) jest wysyłana osobno, pliki są przesyłane jako surowe dane binarne, a nie jako tekst.

  • $_FILES["plik"] - $_FILES to superglobalna tablica z danymi o uploadowanych plikach a "plik" to nazwa pola formularza (name="plik")

  • name - oryginalna nazwa pliku użytkownika

  • tmp_name - po wysłaniu pliku przez użytkownika, php zapisuje go w katalogu tymczasowym (np. /temp). Nadaje mu losową nazwę i udostępnia tę ścieżkę właśnie przez $_FILES["plik"]["tmp_name"];

  • move_uploaded_file() - przenosi plik z katalogu tymczasowego do docelowego (uploads/)

  • isset() – sprawdza, czy plik został przesłany

Bezpieczny upload plików

Najważniejsze zagrożenia:

  • wgranie pliku PHP (atak!)

  • zbyt duży plik

  • nadpisanie istniejącego pliku

  • złośliwa nazwa pliku

Przykład: bezpieczny upload

<?php
if (isset($_FILES["plik"])) {

    $plik = $_FILES["plik"];

    // 1. Sprawdzenie błędów
    if ($plik["error"] !== 0) {
        die("Błąd przesyłania pliku.");
    }

    // 2. Sprawdzenie rozmiaru (max 2MB)
    if ($plik["size"] > 2 * 1024 * 1024) {
        die("Plik jest za duży.");
    }

    // 3. Dozwolone rozszerzenia
    $dozwolone = ["jpg", "png", "txt", "pdf"];
    $rozszerzenie = strtolower(pathinfo($plik["name"], PATHINFO_EXTENSION));

    if (!in_array($rozszerzenie, $dozwolone)) {
        die("Niedozwolony typ pliku.");
    }

    // 4. Generowanie bezpiecznej nazwy
    $nowaNazwa = uniqid() . "." . $rozszerzenie;

    // 5. Przeniesienie pliku
    if (move_uploaded_file($plik["tmp_name"], "uploads/" . $nowaNazwa)) {
        echo "Plik został zapisany.";
    } else {
        echo "Błąd zapisu pliku.";
    }
}
?>

Wyjaśnienie zabezpieczeń:

  1. error - Sprawdza, czy upload przebiegł poprawnie.

  2. Rozmiar pliku - Chroni serwer przed dużymi plikami.

  3. Sprawdzanie rozszerzenia - Pozwala ograniczyć typy plików (np. tylko obrazy i PDF).

  4. uniqid() - tworzy unikalną nazwę pliku, zapobiega nadpisaniu istniejących plików i eliminuje problem z niebezpiecznymi nazwami.

  5. move_uploaded_file() - bezpiecznie przenosi plik i działa tylko dla plików przesłanych przez formularz.

Scandir()

Funkcja scandir() w PHP służy do odczytania zawartości katalogu (folderu).

Najprostszy przykład:

$pliki = scandir(".");

print_r($pliki);

Co tu się dzieje?

  • "." - oznacza aktualny katalog

  • scandir(".") - pobiera listę plików z tego katalogu

  • print_r($pliki) - wyświetla wynik

Wynik działania:

Array
(
    [0] => .
    [1] => ..
    [2] => index.php
    [3] => obrazek.jpg
)

Przykład bez . i ..

$pliki = scandir(".");

foreach ($pliki as $plik) {
    if ($plik != "." && $plik != "..") {
        echo $plik . "<br>";
    }
}

Zadania - Obsługa plików

1. Dziennik odwiedzin

Stwórz formularz, w którym użytkownik wpisuje swoje imię. Po wysłaniu formularza imię wraz z aktualną datą i godziną ma zostać zapisane do pliku log.txt. Następnie wyświetl całą zawartość tego pliku na stronie.

Kroki do wykonania:

  1. Utwórz formularz HTML z polem tekstowym (input type="text").

  2. Sprawdź w PHP, czy formularz został wysłany (isset()).

  3. Pobierz dane użytkownika i usuń zbędne spacje (trim()).

  4. Sprawdź, czy pole nie jest puste (empty()).

  5. Otwórz plik log.txt w trybie dopisywania (fopen(..., "a")).

  6. Zapisz dane w formacie:

    Imię - data i godzina
  7. Zamknij plik (fclose()).

  8. Otwórz ponownie plik w trybie odczytu ("r").

  9. Odczytaj jego zawartość (fread()).

  10. Wyświetl dane na stronie (z użyciem htmlspecialchars()).

2. Prosty system uploadu obrazów

Stwórz formularz umożliwiający przesłanie pliku graficznego. Plik powinien zostać zapisany w folderze images/, a na stronie ma zostać wyświetlona informacja o sukcesie oraz lista wszystkich przesłanych plików.

Kroki do wykonania:

  1. Utwórz formularz z:

  • input type="file"

  • enctype="multipart/form-data"

  1. Sprawdź, czy plik został przesłany (isset($_FILES["plik"])).

  2. Sprawdź, czy nie wystąpił błąd (error).

  3. Ogranicz maksymalny rozmiar pliku (np. 1MB).

  4. Sprawdź rozszerzenie pliku (dozwolone: jpg, png).

  5. Wygeneruj unikalną nazwę pliku (uniqid()).

  6. Przenieś plik do folderu images/ (move_uploaded_file()).

  7. Wyświetl komunikat o powodzeniu lub błędzie.

  8. Odczytaj zawartość folderu images/ (np. scandir()).

  9. Wyświetl listę przesłanych plików (np. jako lista lub obrazy).