Lekcja 8.7: Przesyłanie plików (<input type="file">)
Umożliwienie użytkownikom wysyłania plików
Formularze HTML mogą również służyć do przesyłania plików z komputera użytkownika na serwer. Jest to realizowane za pomocą specjalnego typu pola <input>
: type="file"
.
Pole wyboru pliku: <input type="file">
Znacznik <input type="file">
tworzy przycisk (lub pole tekstowe z przyciskiem, zależnie od przeglądarki), który po kliknięciu otwiera systemowe okno dialogowe wyboru plików.
Kluczowe atrybuty <input type="file">:
type="file"
: Definiuje pole jako kontrolkę do wyboru plików.name
: Niezbędny atrybut, określa nazwę, pod jaką plik (lub pliki) zostaną wysłane na serwer.id
: Unikalny identyfikator, do powiązania z etykietą<label>
.accept
: Opcjonalny atrybut, który sugeruje przeglądarce, jakie typy plików użytkownik powinien móc wybrać. Przeglądarka może użyć tej informacji do filtrowania plików w oknie dialogowym. Wartość to lista typów MIME, rozszerzeń plików lub ogólnych kategorii oddzielonych przecinkami.accept="image/*"
: Dowolne pliki graficzne.accept=".jpg, .jpeg, .png"
: Pliki z określonymi rozszerzeniami.accept="audio/*"
: Dowolne pliki audio.accept="video/*"
: Dowolne pliki wideo.accept="application/pdf"
: Pliki PDF.
accept
jest tylko wskazówką dla przeglądarki i nie zapewnia pełnego bezpieczeństwa. Walidacja typu pliku musi być zawsze przeprowadzona również po stronie serwera!multiple
: Atrybut logiczny. Jeśli jest obecny, użytkownik może wybrać wiele plików jednocześnie w oknie dialogowym (zazwyczaj przytrzymując Ctrl lub Shift).required
: Wymaga, aby użytkownik wybrał przynajmniej jeden plik przed wysłaniem formularza.disabled
: Wyłącza pole wyboru pliku.
Wymaganie dla formularza: `enctype="multipart/form-data"`
Aby formularz mógł poprawnie przesyłać pliki, konieczne jest dodanie do znacznika <form>
atrybutu enctype="multipart/form-data"
. Ten atrybut określa sposób kodowania danych formularza przed wysłaniem na serwer.
- Domyślna wartość
enctype
toapplication/x-www-form-urlencoded
, która nie nadaje się do przesyłania plików. multipart/form-data
oznacza, że dane formularza zostaną podzielone na części (jedna dla każdego pola i każda dla przesyłanego pliku), co jest niezbędne do obsługi binarnej zawartości plików.
Dodatkowo, do przesyłania plików zazwyczaj używa się metody POST
w formularzu (method="POST"
), ponieważ metoda GET
ma ograniczenia co do ilości danych i nie jest przeznaczona do wysyłania zawartości plików.
Przykład formularza do przesyłania jednego pliku (obrazka):
<form action="/upload-avatar" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>Prześlij swój awatar</legend>
<div>
<label for="avatar-file">Wybierz plik obrazka (JPG, PNG):</label>
<input type="file" id="avatar-file" name="avatar" accept=".jpg, .jpeg, .png" required>
</div>
<button type="submit">Prześlij awatar</button>
</fieldset>
</form>
W tym przykładzie:
- Formularz używa
method="POST"
ienctype="multipart/form-data"
. - Pole
<input type="file">
ma nazwęavatar
. - Atrybut
accept
sugeruje wybór plików JPG lub PNG. - Atrybut
required
sprawia, że wybór pliku jest obowiązkowy.
Przykład przesyłania wielu plików:
<form action="/upload-gallery" method="POST" enctype="multipart/form-data">
<label for="gallery-files">Wybierz zdjęcia do galerii (wiele plików):</label>
<input type="file" id="gallery-files" name="zdjecia[]" accept="image/*" multiple>
<button type="submit">Prześlij zdjęcia</button>
</form>
Tutaj atrybut multiple
pozwala na wybór wielu plików, a accept="image/*"
sugeruje wybór dowolnych obrazków. Nazwa pola zdjecia[]
z nawiasami kwadratowymi podpowiada serwerowi, że może otrzymać tablicę plików.
Bezpieczeństwo
Obsługa przesyłanych plików wymaga szczególnej uwagi pod kątem bezpieczeństwa po stronie serwera:
- Zawsze waliduj typ pliku na serwerze: Nie ufaj atrybutowi
accept
ani rozszerzeniu pliku. Sprawdzaj faktyczny typ MIME pliku po stronie serwera. - Ograniczaj rozmiar pliku: Ustaw maksymalny dopuszczalny rozmiar przesyłanego pliku na serwerze, aby zapobiec atakom typu Denial of Service.
- Zmieniaj nazwy plików: Nie używaj oryginalnej nazwy pliku przesłanej przez użytkownika jako nazwy pliku na serwerze. Generuj unikalne, bezpieczne nazwy, aby uniknąć nadpisywania plików i potencjalnych problemów z niebezpiecznymi znakami w nazwach.
- Przechowuj pliki poza głównym katalogiem webowym: Jeśli to możliwe, przechowuj przesłane pliki w katalogu niedostępnym bezpośrednio przez URL, aby zapobiec ich bezpośredniemu wykonaniu (np. skryptów PHP, jeśli serwer jest źle skonfigurowany). Dostęp do plików powinien być kontrolowany przez skrypt serwerowy.
- Skanuj pliki antywirusem: Jeśli to krytyczne, rozważ skanowanie przesyłanych plików na serwerze.
Zadanie praktyczne (z rozwiązaniem)
Zadanie: Dodaj do formularza kontaktowego możliwość załączenia pliku (np. zrzutu ekranu). Użyj <input type="file">
. Pamiętaj o dodaniu odpowiedniego atrybutu enctype
do znacznika <form>
. Ogranicz akceptowane typy plików do obrazków.
Rozwiązanie:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Formularz Kontaktowy - Przesyłanie Plików</title>
<style>
/* Style z poprzednich lekcji */
label { display: block; margin-top: 10px; }
input[type="text"], input[type="password"], textarea, select, input[type="file"] { width: 90%; max-width: 300px; padding: 8px; margin-top: 5px; border: 1px solid #ccc; }
button, input[type="submit"], input[type="reset"], input[type="button"] { margin-top: 15px; padding: 10px 15px; margin-right: 10px; cursor: pointer; }
fieldset { border: 1px dashed #aaa; padding: 15px; margin-bottom: 20px; }
legend { font-weight: bold; color: navy; padding: 0 5px; }
fieldset div { margin-bottom: 8px; }
input[type="radio"], input[type="checkbox"] { margin-right: 5px; }
fieldset > div > label { display: block; margin-top: 10px; }
fieldset > div > input + label { display: inline-block; margin-top: 0; }
</style>
</head>
<body>
<h1>Kontakt</h1>
<!-- Dodano enctype="multipart/form-data" i method="POST" -->
<form action="/wyslij-wiadomosc" method="POST" enctype="multipart/form-data">
<fieldset>
<legend>Dane wiadomości</legend>
<div>
<label for="contact-imie">Imię:</label>
<input type="text" id="contact-imie" name="imie_uzytkownika" required>
</div>
<div>
<label for="contact-dzial">Dział:</label>
<select id="contact-dzial" name="dzial" required>
<option value="">-- Wybierz dział --</option>
<option value="sprzedaz">Sprzedaż</option>
<option value="pomoc">Pomoc techniczna</option>
<option value="reklamacje">Reklamacje</option>
<option value="inne">Inne</option>
</select>
</div>
<div>
<label for="contact-wiadomosc">Wiadomość:</label>
<textarea id="contact-wiadomosc" name="tresc_wiadomosci" rows="4" required></textarea>
</div>
<!-- Dodane pole do przesyłania pliku -->
<div>
<label for="contact-attachment">Załącznik (opcjonalnie, tylko obrazki):</label>
<input type="file" id="contact-attachment" name="zalacznik" accept="image/*">
</div>
</fieldset>
<button type="submit">Wyślij wiadomość</button>
<button type="reset">Wyczyść formularz</button>
</form>
</body>
</html>
Dodatkowe zadania do samodzielnego wykonania:
- Zmień atrybut
accept
, aby akceptował tylko pliki PDF. - Dodaj atrybut
multiple
do pola przesyłania plików, aby umożliwić wysłanie wielu załączników. - Dodaj drugie pole
<input type="file">
do przesyłania innego rodzaju pliku (np. dokumentu tekstowego).
Najczęściej zadawane pytania
Jak stworzyć pole do przesyłania plików w HTML?
Użyj znacznika <input type="file">. Pamiętaj o nadaniu mu atrybutu name. Cały formularz musi mieć dodatkowo atrybut enctype="multipart/form-data" oraz zazwyczaj method="POST".
Do czego służy atrybut enctype="multipart/form-data"?
Jest niezbędny do poprawnego przesyłania plików. Informuje przeglądarkę, aby zakodowała dane formularza w specjalny sposób (dzieląc je na części), który umożliwia wysłanie binarnej zawartości plików.
Jak ograniczyć typy plików, które użytkownik może wybrać?
Użyj atrybutu accept w <input type="file">, podając listę akceptowanych typów MIME (np. "image/jpeg"), rozszerzeń (np. ".pdf") lub kategorii (np. "audio/*"). Pamiętaj, że to tylko wskazówka - walidacja na serwerze jest konieczna.
Jak pozwolić na przesyłanie wielu plików naraz?
Dodaj atrybut logiczny multiple do znacznika <input type="file">. Użytkownik będzie mógł wybrać wiele plików w oknie dialogowym.
Czy przesyłanie plików jest bezpieczne?
Wymaga szczególnej ostrożności po stronie serwera. Należy zawsze walidować typ i rozmiar pliku, generować bezpieczne nazwy i odpowiednio przechowywać pliki, aby zapobiec atakom i problemom bezpieczeństwa.