# Kā PHP apstrādā failu augšupielādes

> Kā PHP iekšēji apstrādā failu augšupielādes: multipart/form-data, pagaidu faili upload_tmp_dir, masīvs $_FILES, robežvērtības un kļūdu kodi.

Avots: https://phpsos.de/lv/php/datei-uploads-intern/  
Aktuāls uz: 25.10.2026  
Pakalpojuma sniedzējs: PHP SOS, PHP ārkārtas palīdzība un serveru drošība. Tūlītēja palīdzība pa WhatsApp: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20nepiecie%C5%A1ama%20pal%C4%ABdz%C4%ABba%20ar%20m%C5%ABsu%20PHP%20serveri.%20Uz%C5%86%C4%93mums%3A%20%E2%80%A6%20Vietne%3A%20%E2%80%A6

**Īsi:** kad pārlūkprogramma augšupielādē failu, tā sūta POST pieprasījumu formātā `multipart/form-data`, kurā veidlapas lauki un faila saturs ir secīgas atsevišķas daļas. PHP pats sadala šo pieprasījumu, ieraksta katru faila daļu pagaidu failā direktorijā `upload_tmp_dir`, ievada datus masīvā `$_FILES` un tikai tad startē jūsu skriptu. Skripts failu pārvieto ar `move_uploaded_file()`; visu, kas netiek pārvietots, PHP izdzēš pieprasījuma beigās.

## Faila ceļš no pārlūkprogrammas līdz skriptam

Lēmumu pieņēmējiem svarīgākais ir tas, ka augšupielāde nav tikai lietojumprogrammas darbība. Liela daļa darba notiek PHP interpretatorā, pirms CMS vai veikala kods vispār tiek iesaistīts. Tāpēc kļūdas šajā PHP daļā skar katru vietni neatkarīgi no tā, vai tai ir augšupielādes veidlapa.

Norises kopskats:

1. Tiek nosūtīta veidlapa ar `method="POST"` un `enctype="multipart/form-data"`.
2. Tīmekļa serveris pieņem pieprasījumu un nodod to PHP, atkarībā no darbības režīma ar PHP-FPM, mod_php vai citu saskarni.
3. PHP pārbauda robežvērtības, piemēram, `post_max_size`, un sadala saturu pēc atdalītāja rindas, tā sauktā Boundary.
4. Parastie lauki nonāk `$_POST`, faila daļas tiek ierakstītas pagaidu failos un aprakstītas `$_FILES`.
5. Tikai tagad startē skripts, pārbauda failu un pārvieto to uz mērķa vietu.
6. Pieprasījuma beigās PHP izdzēš visus pagaidu failus, kas nav pārvietoti.

## multipart/form-data: augšupielādes pieprasījuma uzbūve

Augšupielādes pieprasījums ir tīrs teksts ar iegultiem faila datiem. Galvene `Content-Type` nosauc Boundary, un saturā šī rinda atdala atsevišķās daļas. Katrai daļai ir savas galvenes rindas ar lauka nosaukumu un, ja nepieciešams, faila nosaukumu. Ļoti saīsināts, nekaitīgs piemērs:

```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--
```

Visas šī teksta ziņas nāk no sūtītāja, arī faila nosaukums un daļas `Content-Type`. PHP tās pārņem `$_FILES`, bet nepārbauda, vai tās ir ticamas.

## Masīvs $_FILES

Laukam ar nosaukumu `lebenslauf` masīvs `$_FILES['lebenslauf']` saskaņā ar PHP rokasgrāmatu satur šādas atslēgas:

| Atslēga | Saturs | Vai uzticams? |
|---|---|---|
| `name` | sākotnējais faila nosaukums pie sūtītāja | nē |
| `full_path` | pārlūkprogrammas paziņotais ceļš, kopš PHP 8.1.0 | nē |
| `type` | MIME tips pēc pārlūkprogrammas, PHP to nepārbauda | nē |
| `size` | izmērs baitos | to nosaka PHP |
| `tmp_name` | pagaidu faila ceļš serverī | to piešķir PHP |
| `error` | augšupielādes apstrādes kļūdas kods | to iestata PHP |

Laukiem ar kvadrātiekavām nosaukumā, piemēram, `bilder[]`, katra atslēga satur masīvu ar vienu ierakstu katram failam. Lietojumprogramma tad iet cauri, piemēram, `$_FILES['bilder']['error']`, un ar to pašu indeksu piekļūst `tmp_name` un `name`.

Veidlapa var papildus pirms faila lauka nosūtīt slēptu lauku `MAX_FILE_SIZE`. Saskaņā ar rokasgrāmatu tā ir tikai norāde pārlūkprogrammai, ko viegli apiet. Uzticēties var tikai robežām, ko īsteno serveris: PHP, tīmekļa serverī un pašā lietojumprogrammā.

## Robežvērtības: php.ini direktīvas augšupielādēm

Šīs direktīvas vada augšupielādes apstrādi. Noklusējuma vērtības ņemtas no PHP rokasgrāmatas un ir spēkā, ja php.ini tās nepārraksta.

| Direktīva | Noklusējums | Maināms kur |
|---|---|---|
| `file_uploads` | `1` | tikai sistēmas konfigurācijā |
| `upload_tmp_dir` | tukšs (sistēmas pagaidu direktorijs) | tikai sistēmas konfigurācijā |
| `upload_max_filesize` | `2M` | php.ini, pūls, direktorija konfigurācija |
| `post_max_size` | `8M` | php.ini, pūls, direktorija konfigurācija |
| `max_file_uploads` | `20` | php.ini, pūls, direktorija konfigurācija |
| `enable_post_data_reading` | `1` | php.ini, pūls, direktorija konfigurācija |

`post_max_size` jābūt lielākam par `upload_max_filesize`, un `memory_limit` saskaņā ar rokasgrāmatu parasti jābūt lielākam par `post_max_size`. Ja `upload_tmp_dir` nav rakstāms, PHP pāriet uz sistēmas pagaidu direktoriju. Ar `open_basedir` pagaidu direktorijam jābūt atļautam, citādi augšupielādes neizdodas. Praktiskās vērtības un to sekas apraksta raksts [post_max_size un upload_max_filesize saprātīga ierobežošana](https://phpsos.de/lv/blog/post-max-size-upload-limits/).

## Kļūdu kodu pareiza izvērtēšana

Lauks `error` norāda, kas apstrādes laikā noticis. Konstantes iet no `UPLOAD_ERR_OK` (0) cauri `UPLOAD_ERR_INI_SIZE` (1), `UPLOAD_ERR_FORM_SIZE` (2), `UPLOAD_ERR_PARTIAL` (3) un `UPLOAD_ERR_NO_FILE` (4) līdz `UPLOAD_ERR_NO_TMP_DIR` (6), `UPLOAD_ERR_CANT_WRITE` (7) un `UPLOAD_ERR_EXTENSION` (8).

```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);
}
```

Piemērs rāda tikai mehāniku. Faila tipa pārbaudi, glabāšanu ārpus webroot un skriptu izpildes bloķēšanu apraksta ceļvedis [Failu augšupielādes PHP drošā īstenošana](https://phpsos.de/lv/ratgeber/datei-upload-sicher/).

## Augšupielādes un PHP2Shell: ko nozīmē pagaidu pasākumi

PHP2Shell ievainojamības CVE-2026-109618 un CVE-2026-109619 skar pieprasījuma apstrādi PHP interpretatorā. Tāpēc php.net kā pagaidu pasākumus min, cita starpā, `post_max_size = 8M` (bez augšupielādēm) vai `32M` (ar augšupielādēm), zemāku `upload_max_filesize` un `session.upload_progress.enabled=0`. Šīm vērtībām jābūt php.ini, FPM pūlā vai servera konfigurācijā, pēc tam jāpārstartē visi darbprocesi.

Speciālisti papildus iesaka bloķēt `multipart/form-data` pieprasījumus ārpus īstajiem augšupielādes ceļiem starpniekserverī vai WAF. Tas ir neoficiāls pasākums ar risku, ka veidlapas pārstās darboties; izvērtējumu apraksta raksts [Augšupielādes pieprasījumu filtrēšana tīkla malā](https://phpsos.de/lv/blog/upload-anfragen-am-rand-filtern/). Neviens no šiem pasākumiem neaizstāj atjauninājumu uz PHP 8.5.12, 8.4.27, 8.3.36 vai 8.2.35.

## Kā PHP SOS palīdz konkrēti?

- Mēs noskaidrojam, kurām jūsu vietnēm augšupielādes patiešām vajadzīgas un kādos ceļos.
- Mēs iestatām robežvērtības un pagaidu pasākumus katram pūlam, pārstartējam visus darbprocesus un testējam veidlapas.
- Mēs pārbaudām augšupielāžu direktorijus uz izpildāmiem failiem un bloķējam skriptu izpildi [servera nostiprināšanas](https://phpsos.de/lv/leistungen/server-haertung/) ietvaros.
- Mēs ieviešam PHP atjauninājumu un dokumentējam ielāpu stāvokli katrai vietnei.


## Biežāk uzdotie jautājumi

**Kur PHP vispirms saglabā augšupielādētos failus?**  
Pagaidu direktorijā. Pēc noklusējuma tas ir sistēmas pagaidu direktorijs; to var mainīt ar upload_tmp_dir. Ja skriptā fails netiek pārvietots, PHP to izdzēš pieprasījuma beigās.

**Vai laukam type masīvā $_FILES var uzticēties?**  
Nē. MIME tipu paziņo pārlūkprogramma, un saskaņā ar rokasgrāmatu PHP to nepārbauda. Arī name un full_path nāk no sūtītāja. Faktisko faila tipu nosakiet servera pusē pēc satura.

**Kāpēc $_FILES ir tukšs, kaut gan fails tika nosūtīts?**  
Visbiežāk viss pieprasījums bija lielāks par post_max_size. Tad PHP pilnībā iztukšo $_POST un $_FILES, un masīvā nav kļūdas koda. Citi iemesli ir trūkstošs enctype veidlapā vai izslēgts file_uploads.

**Vai pret PHP2Shell palīdz augšupielāžu aizliegšana lietojumprogrammā?**  
Nē. Pieprasījuma datu apstrāde notiek PHP, pirms darbojas lietojumprogrammas kods. Efektīvi ir PHP atjauninājums un visu darbprocesu pārstartēšana; šaurākas robežvērtības ir tikai pagaidu pasākums.

**Kāda ir atšķirība starp upload_max_filesize un post_max_size?**  
upload_max_filesize ierobežo katru atsevišķo failu, post_max_size visu pieprasījuma saturu, ieskaitot visus failus un laukus. Tāpēc post_max_size jābūt lielākam par upload_max_filesize.

## Avoti

- [PHP rokasgrāmata: augšupielādes ar POST](https://www.php.net/manual/de/features.file-upload.post-method.php)
- [PHP rokasgrāmata: kļūdu ziņojumi augšupielādēs](https://www.php.net/manual/de/features.file-upload.errors.php)
- [PHP rokasgrāmata: php.ini direktīvas](https://www.php.net/manual/de/ini.core.php)
- [php.net: drošības paziņojumi](https://www.php.net/)
