# Hogyan dolgozza fel a PHP a fájlfeltöltést

> Hogyan dolgozza fel a PHP belül a fájlfeltöltést: multipart/form-data, ideiglenes fájlok az upload_tmp_dir-ben, a $_FILES tömb, korlátok és hibakódok.

Forrás: https://phpsos.de/hu/php/datei-uploads-intern/  
Állapot: 2026. 10. 25.  
Szolgáltató: PHP SOS, PHP-vészhelyzeti segítség és szerverbiztonság. Azonnali segítség WhatsAppon: https://wa.me/491736494914?text=%C3%9Cdv%C3%B6zl%C3%B6m%2C%20PHP%20SOS%21%20Seg%C3%ADts%C3%A9gre%20van%20sz%C3%BCks%C3%A9g%C3%BCnk%20a%20PHP-szerver%C3%BCnkkel.%20C%C3%A9g%3A%20%E2%80%A6%20Weboldal%3A%20%E2%80%A6

**Röviden:** Amikor egy böngésző fájlt tölt fel, `multipart/form-data` formátumú POST-kérést küld, amelyben az űrlapmezők és a fájltartalmak külön részekként követik egymást. A PHP ezt a kérést maga bontja szét, minden fájlrészt ideiglenes fájlba ír az `upload_tmp_dir` könyvtárban, bejegyzi az adatokat a `$_FILES`-ba, és csak ezután indítja el az Ön szkriptjét. A szkript a `move_uploaded_file()` függvénnyel helyezi át a fájlt; amit nem helyez át, azt a PHP a kérés végén törli.

## A fájl útja a böngészőtől a szkriptig

A döntéshozók számára elsősorban egy dolog fontos: a feltöltés nem pusztán az alkalmazás ügye. A munka nagy része a PHP-értelmezőben zajlik, még mielőtt a CMS vagy a webshop kódja egyáltalán részt venne benne. Ezért a PHP ezen részének hibái minden weboldalt érintenek, akár van feltöltési űrlapja, akár nincs.

A folyamat áttekintése:

1. Elküldik az űrlapot `method="POST"` és `enctype="multipart/form-data"` beállítással.
2. A webszerver elfogadja a kérést, és továbbadja a PHP-nak, az üzemmódtól függően PHP-FPM-en, mod_php-n vagy más felületen keresztül.
3. A PHP ellenőrzi a korlátokat, például a `post_max_size`-t, és egy elválasztó karaktersorozat, az úgynevezett boundary mentén felbontja a tartalmat.
4. A normál mezők a `$_POST`-ba kerülnek, a fájlrészeket ideiglenes fájlokba írja a PHP, és leírja őket a `$_FILES`-ban.
5. Csak most indul el a szkript, ellenőrzi a fájlt, és a célhelyére helyezi.
6. A kérés végén a PHP törli az összes ideiglenes fájlt, amelyet nem helyeztek át.

## multipart/form-data: a feltöltési kérés felépítése

A feltöltési kérés tiszta szöveg, beágyazott fájladatokkal. A `Content-Type` fejléc megadja a boundary-t, a tartalomban pedig ez a karaktersorozat választja el egymástól az egyes részeket. Minden résznek saját fejlécsorai vannak a mezőnévvel és adott esetben a fájlnévvel. Egy erősen lerövidített, ártalmatlan példa:

```http
POST /bewerbung HTTP/1.1
Content-Type: multipart/form-data; boundary=----trenner42

------trenner42
Content-Disposition: form-data; name="vorname"

Erika
------trenner42
Content-Disposition: form-data; name="lebenslauf"; filename="lebenslauf.pdf"
Content-Type: application/pdf

%PDF-1.7 ... Dateiinhalt ...
------trenner42--
```

Ebben a szövegben minden adat a feladótól származik, a fájlnév és a rész `Content-Type`-ja is. A PHP átveszi őket a `$_FILES`-ba, de hihetőségüket nem ellenőrzi.

## A $_FILES tömb

A `lebenslauf` nevű mező esetén a `$_FILES['lebenslauf']` a PHP-kézikönyv szerint ezeket a kulcsokat tartalmazza:

| Kulcs | Tartalom | Megbízható? |
|---|---|---|
| `name` | a fájl eredeti neve a feladónál | nem |
| `full_path` | a böngésző által jelentett útvonal, a PHP 8.1.0 óta | nem |
| `type` | a böngésző szerinti MIME-típus, a PHP nem ellenőrzi | nem |
| `size` | méret bájtban | a PHP állapítja meg |
| `tmp_name` | az ideiglenes fájl útvonala a szerveren | a PHP adja |
| `error` | a feltöltés-feldolgozás hibakódja | a PHP állítja be |

Szögletes zárójeles nevű mezőknél, például `bilder[]`, minden kulcs egy tömböt tartalmaz fájlonként egy bejegyzéssel. Az alkalmazás ilyenkor például a `$_FILES['bilder']['error']`-on megy végig, és ugyanazzal az indexszel éri el a `tmp_name`-et és a `name`-et.

Az űrlap emellett küldhet a fájlmező előtt egy rejtett `MAX_FILE_SIZE` mezőt. A kézikönyv szerint ez csupán tanács a böngészőnek, amely könnyen megkerülhető. Kizárólag azokra a korlátokra támaszkodhat, amelyeket a szerver érvényesít: a PHP-ban, a webszerverben és magában az alkalmazásban.

## Korlátok: a feltöltések php.ini-direktívái

Ezek a direktívák vezérlik a feltöltések feldolgozását. Az alapértékek a PHP-kézikönyvből származnak, és akkor érvényesek, ha egy php.ini nem írja felül őket.

| Direktíva | Alapérték | Módosítható itt |
|---|---|---|
| `file_uploads` | `1` | csak rendszerkonfiguráció |
| `upload_tmp_dir` | üres (rendszer ideiglenes könyvtára) | csak rendszerkonfiguráció |
| `upload_max_filesize` | `2M` | php.ini, pool, könyvtárkonfiguráció |
| `post_max_size` | `8M` | php.ini, pool, könyvtárkonfiguráció |
| `max_file_uploads` | `20` | php.ini, pool, könyvtárkonfiguráció |
| `enable_post_data_reading` | `1` | php.ini, pool, könyvtárkonfiguráció |

A `post_max_size`-nak nagyobbnak kell lennie az `upload_max_filesize`-nál, a `memory_limit`-nek pedig a kézikönyv szerint általában nagyobbnak kell lennie a `post_max_size`-nál. Ha az `upload_tmp_dir` nem írható, a PHP a rendszer ideiglenes könyvtárára tér át. Az `open_basedir` használatakor az ideiglenes könyvtárnak engedélyezettnek kell lennie, különben a feltöltések meghiúsulnak. A gyakorlati értékeket és következményeiket a [post_max_size és upload_max_filesize ésszerű korlátozása](https://phpsos.de/hu/blog/post-max-size-upload-limits/) cikk írja le.

## A hibakódok helyes kiértékelése

Az `error` mező megmondja, mi történt a feldolgozás során. A konstansok az `UPLOAD_ERR_OK` (0) értéktől az `UPLOAD_ERR_INI_SIZE` (1), `UPLOAD_ERR_FORM_SIZE` (2), `UPLOAD_ERR_PARTIAL` (3) és `UPLOAD_ERR_NO_FILE` (4) értéken át az `UPLOAD_ERR_NO_TMP_DIR` (6), `UPLOAD_ERR_CANT_WRITE` (7) és `UPLOAD_ERR_EXTENSION` (8) értékig terjednek.

```php
<?php
declare(strict_types=1);

$datei = $_FILES['lebenslauf'] ?? null;
if ($datei === null) {
    exit('Keine Upload-Daten, eventuell wurde post_max_size überschritten.');
}

$meldung = match ($datei['error']) {
    UPLOAD_ERR_OK => null,
    UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE => 'Datei zu groß.',
    UPLOAD_ERR_NO_FILE => 'Keine Datei gewählt.',
    default => 'Upload fehlgeschlagen.',
};

if ($meldung === null && is_uploaded_file($datei['tmp_name'])) {
    $ziel = '/srv/app/uploads/' . bin2hex(random_bytes(16)) . '.pdf';
    move_uploaded_file($datei['tmp_name'], $ziel);
}
```

A példa csak a működési mechanizmust mutatja. A fájltípus ellenőrzését, a webgyökéren kívüli tárolást és a szkriptfuttatás tiltását a [Fájlfeltöltések biztonságos megvalósítása PHP-ban](https://phpsos.de/hu/ratgeber/datei-upload-sicher/) útmutató írja le.

## Feltöltések és PHP2Shell: mit jelentenek az átmeneti intézkedések

A CVE-2026-109618 és CVE-2026-109619 számú PHP2Shell-rések a kérés körüli feldolgozást érintik a PHP-értelmezőben. Ezért a php.net átmeneti intézkedésként többek között a `post_max_size = 8M` (feltöltések nélkül) vagy `32M` (feltöltésekkel) értéket, az `upload_max_filesize` ennél alacsonyabb értékét, valamint a `session.upload_progress.enabled=0` beállítást nevezi meg. Ezeket az értékeket a php.ini-be, az FPM-poolba vagy a szerverkonfigurációba kell írni, utána pedig minden workert újra kell indítani.

Szakmai szerzők emellett azt javasolják, hogy a valódi feltöltési útvonalakon kívüli `multipart/form-data` kéréseket a proxyn vagy a WAF-on blokkolják. Ez nem hivatalos intézkedés, és fennáll a kockázata, hogy az űrlapok elromlanak; a mérlegelést az [Upload-kérések szűrése a peremen](https://phpsos.de/hu/blog/upload-anfragen-am-rand-filtern/) cikk írja le. Ezen intézkedések egyike sem helyettesíti a frissítést a PHP 8.5.12, 8.4.27, 8.3.36 vagy 8.2.35 verzióra.

## Hogyan segít konkrétan a PHP SOS?

- Megállapítjuk, hogy az Ön weboldalai közül melyeknek van ténylegesen szükségük feltöltésekre, és mely útvonalakon.
- Poolonként beállítjuk a korlátokat és az átmeneti intézkedéseket, újraindítjuk az összes workert, és teszteljük az űrlapokat.
- Ellenőrizzük a feltöltési könyvtárakat futtatható fájlok szempontjából, és a [szerverkeményítés](https://phpsos.de/hu/leistungen/server-haertung/) keretében letiltjuk a szkriptfuttatást.
- Telepítjük a PHP-frissítést, és weboldalanként dokumentáljuk a javítási állapotot.


## Gyakori kérdések

**Hová menti a PHP elsőként a feltöltött fájlokat?**  
Egy ideiglenes könyvtárba. Alapértelmezés szerint ez a rendszer ideiglenes könyvtára, amely az upload_tmp_dir-rel módosítható. Ha a szkript nem helyezi át a fájlt, a PHP a kérés végén törli.

**Megbízhatok a $_FILES type mezőjében?**  
Nem. Az MIME-típust a böngésző jelenti, a PHP a kézikönyv szerint nem ellenőrzi. A name és a full_path is a feladótól származik. A tényleges fájltípust a szerveroldalon, a tartalom alapján állapítsa meg.

**Miért üres a $_FILES, pedig küldtek fájlt?**  
Többnyire a teljes kérés nagyobb volt a post_max_size-nál. Ilyenkor a PHP teljesen kiüríti a $_POST-ot és a $_FILES-t, a tömbben hibakód nélkül. További okok: hiányzó enctype az űrlapban vagy kikapcsolt file_uploads.

**Segít a PHP2Shell ellen, ha az alkalmazásban megtiltom a feltöltéseket?**  
Nem. A kéradatok feldolgozása a PHP-ban történik, még az alkalmazáskód futása előtt. A PHP-frissítés és az összes worker újraindítása hatásos; a szűkebb korlátok csak átmeneti intézkedések.

**Mi a különbség az upload_max_filesize és a post_max_size között?**  
Az upload_max_filesize az egyes fájlokat korlátozza, a post_max_size a kérés teljes tartalmát az összes fájllal és mezővel együtt. A post_max_size-nak ezért nagyobbnak kell lennie az upload_max_filesize-nál.

## Források

- [PHP-kézikönyv: Feltöltések POST-tal](https://www.php.net/manual/de/features.file-upload.post-method.php)
- [PHP-kézikönyv: Hibaüzenetek feltöltéskor](https://www.php.net/manual/de/features.file-upload.errors.php)
- [PHP-kézikönyv: php.ini-direktívák](https://www.php.net/manual/de/ini.core.php)
- [php.net: Biztonsági közlemények](https://www.php.net/)
