CZĘŚĆ 19
System plików i przesyłanie plików na serwer (upload)
PPrezentacja dla nauczyciela
W wielu zadaniach egzaminacyjnych INF.03 dane nie trafiają wyłącznie do bazy danych, ale są również zapisywane w plikach tekstowych (np. dzienniki logów, raporty CSV) lub przesyłane z formularza przez użytkownika (np. zdjęcia produktów, załączniki). W tej części opanujesz operacje na systemie plików oraz bezpieczny mechanizm przesyłania plików za pomocą tablicy $_FILES i funkcji move_uploaded_file().
Odczyt i zapis plików
Do pracy z plikami służą file_get_contents() (odczyt całości) i file_put_contents() (zapis). Są proste, ale wczytują cały plik do pamięci.
Przy dużych plikach lepsze są fopen(), fgets() i fclose(), które czytają linia po linii. Tryb otwarcia określa, czy plik ma być czytany, dopisywany czy nadpisany.
Każda operacja na plikach wymaga sprawdzenia wyniku. Brak praw zapisu albo nieistniejący katalog to najczęstsze przyczyny błędów, a nie błędy w samym kodzie.
$sciezka = __DIR__ . '/dane/log.txt';
file_put_contents($sciezka, date('Y-m-d H:i') . " start\n", FILE_APPEND);
if (is_file($sciezka)) {
$linie = file($sciezka, FILE_IGNORE_NEW_LINES);
foreach ($linie as $linia) {
echo '<p>' . htmlspecialchars($linia) . '</p>';
}
}
Przesyłanie pliku na serwer
Formularz z plikiem wymaga method="post" i atrybutu enctype="multipart/form-data". Bez enctype przeglądarka wyśle tylko nazwę pliku.
Dane trafiają do tablicy $_FILES z kluczami name, tmp_name, size i error. Plik trzeba przenieść z katalogu tymczasowego funkcją move_uploaded_file().
Zawsze sprawdzamy kod błędu, rozmiar i rozszerzenie. Nazwę pliku generujemy sami, żeby uniknąć nadpisania i dziwnych znaków w adresie.
if (($_FILES['plik']['error'] ?? 1) === UPLOAD_ERR_OK) {
$nazwa = basename($_FILES['plik']['name']);
$koncowka = strtolower(pathinfo($nazwa, PATHINFO_EXTENSION));
if (in_array($koncowka, ['jpg', 'png'], true) && $_FILES['plik']['size'] < 2000000) {
$nowa = uniqid('img_', true) . '.' . $koncowka;
move_uploaded_file($_FILES['plik']['tmp_name'], __DIR__ . '/upload/' . $nowa);
echo 'Zapisano: ' . htmlspecialchars($nowa);
} else {
echo 'Nieprawidlowy plik';
}
}
Bezpieczeństwo plików i katalogów
Największe ryzyko to wykonanie przesłanego pliku. Jeśli użytkownik wgra plik .php do katalogu publicznego, serwer może go uruchomić. Dlatego sprawdzamy rozszerzenie i zapisujemy pliki poza katalogiem z kodem.
Nazwę pliku budujemy sami i nie ufamy $_FILES['name']. Znaki ../ w nazwie mogą wskazać inny katalog — to tak zwana path traversal.
Dodatkowo ograniczamy rozmiar i typ MIME, a katalogowi uploadu odbieramy prawo wykonywania skryptów. To kilka linii konfiguracji, które zamykają najczęstszą lukę.
$dozwolone = ['jpg' => 'image/jpeg', 'png' => 'image/png'];
$rozszerzenie = strtolower(pathinfo($_FILES['plik']['name'] ?? '', PATHINFO_EXTENSION));
$typ = $_FILES['plik']['type'] ?? '';
if (!isset($dozwolone[$rozszerzenie]) || $dozwolone[$rozszerzenie] !== $typ) {
exit('Niedozwolony typ pliku');
}
$nazwa = bin2hex(random_bytes(8)) . '.' . $rozszerzenie;
move_uploaded_file($_FILES['plik']['tmp_name'], __DIR__ . '/upload/' . $nazwa);
Ćwiczenia
- 1Pierwszy zapis do pliku (file_put_contents)file_put_contents i bajtyZadanie i podpowiedzi →
- 2Dziennik zdarzeń z dopisywaniem (FILE_APPEND)flaga FILE_APPEND i PHP_EOLZadanie i podpowiedzi →
- 3Bezpieczny odczyt z weryfikacją pliku (file_exists)file_exists i file_get_contentsZadanie i podpowiedzi →
- 4Formatowanie pliku z zachowaniem linii (nl2br)kolejność nl2br i encjiZadanie i podpowiedzi →
- 5Odczyt pliku do tablicy linii (file)file z flagami w pętliZadanie i podpowiedzi →
- 6Zapis rekordu do formatu CSVimplode ze średnikiem do plikuZadanie i podpowiedzi →
- 7Odczyt pliku CSV do tabeli HTMLexplode wierszy CSV do komórek tdZadanie i podpowiedzi →
- 8Eksport raportu z bazy MySQL do plikukwerenda z bazy zapisana w plikuZadanie i podpowiedzi →
- 9Formularz z enctype i pierwszy odczyt $_FILESname i size z tablicy FILESZadanie i podpowiedzi →
- 10Sprawdzenie kodu błędu UPLOAD_ERR_OKweryfikacja statusu uploaduZadanie i podpowiedzi →
- 11Obsługa braku wybranego pliku (UPLOAD_ERR_NO_FILE)UPLOAD_ERR_NO_FILE i błąd 4Zadanie i podpowiedzi →
- 12Limit rozmiaru pliku w bajtachkontrola limitu bajtów na serwerzeZadanie i podpowiedzi →
- 13Weryfikacja rozszerzenia przez pathinfoPATHINFO_EXTENSION i biała listaZadanie i podpowiedzi →
- 14Przeniesienie pliku do folderu obrazy (move_uploaded_file)zapis przez move_uploaded_fileZadanie i podpowiedzi →
- 15Bezpieczna unikalna nazwa pliku (uniqid)generowanie nazwy przez uniqidZadanie i podpowiedzi →
- 16Dodanie usługi z załączonym zdjęciem (synteza INF.03)upload, zapis i baza (synteza)Zadanie i podpowiedzi →