# Πώς η PHP επεξεργάζεται τις μεταφορτώσεις αρχείων

> Πώς η PHP επεξεργάζεται εσωτερικά τις μεταφορτώσεις αρχείων: multipart/form-data, προσωρινά αρχεία στο upload_tmp_dir, ο πίνακας $_FILES, όρια και κωδικοί σφάλματος.

Πηγή: https://phpsos.de/el/php/datei-uploads-intern/  
Ημερομηνία: 25/10/2026  
Πάροχος: PHP SOS, Επείγουσα βοήθεια PHP και ασφάλεια διακομιστών. Άμεση βοήθεια μέσω WhatsApp: https://wa.me/491736494914?text=%CE%93%CE%B5%CE%B9%CE%B1%20%CF%83%CE%B1%CF%82%2C%20PHP%20SOS%2C%20%CF%87%CF%81%CE%B5%CE%B9%CE%B1%CE%B6%CF%8C%CE%BC%CE%B1%CF%83%CF%84%CE%B5%20%CE%B2%CE%BF%CE%AE%CE%B8%CE%B5%CE%B9%CE%B1%20%CE%BC%CE%B5%20%CF%84%CE%BF%CE%BD%20%CE%B4%CE%B9%CE%B1%CE%BA%CE%BF%CE%BC%CE%B9%CF%83%CF%84%CE%AE%20PHP%20%CE%BC%CE%B1%CF%82.%20%CE%95%CF%84%CE%B1%CE%B9%CF%81%CE%B5%CE%AF%CE%B1%3A%20%E2%80%A6%20%CE%99%CF%83%CF%84%CF%8C%CF%84%CE%BF%CF%80%CE%BF%CF%82%3A%20%E2%80%A6

**Εν συντομία:** Όταν ένα πρόγραμμα περιήγησης μεταφορτώνει ένα αρχείο, στέλνει ένα αίτημα POST σε μορφή `multipart/form-data`, στο οποίο τα πεδία της φόρμας και τα περιεχόμενα των αρχείων βρίσκονται ως ξεχωριστά τμήματα το ένα μετά το άλλο. Η PHP αναλύει η ίδια αυτό το αίτημα, γράφει κάθε τμήμα αρχείου σε ένα προσωρινό αρχείο στο `upload_tmp_dir`, καταχωρίζει τα στοιχεία στο `$_FILES` και μόνο τότε ξεκινά το σενάριό σας. Το σενάριο μετακινεί το αρχείο με το `move_uploaded_file()`· ό,τι δεν μετακινηθεί, η PHP το διαγράφει στο τέλος του αιτήματος.

## Η διαδρομή ενός αρχείου από το πρόγραμμα περιήγησης ως το σενάριο

Για όσους αποφασίζουν, το πιο σημαντικό είναι το εξής: μια μεταφόρτωση δεν είναι διαδικασία που αφορά μόνο την εφαρμογή. Ένα μεγάλο μέρος της δουλειάς γίνεται στον διερμηνέα της PHP, πριν εμπλακεί καν ο κώδικας του CMS ή του ηλεκτρονικού καταστήματος. Γι' αυτό τα σφάλματα σε αυτό το τμήμα της PHP αφορούν κάθε ιστότοπο, ανεξάρτητα από το αν διαθέτει φόρμα μεταφόρτωσης.

Η διαδικασία με μια ματιά:

1. Υποβάλλεται η φόρμα με `method="POST"` και `enctype="multipart/form-data"`.
2. Ο διακομιστής ιστού δέχεται το αίτημα και το περνά στην PHP, ανάλογα με τον τρόπο λειτουργίας μέσω PHP-FPM, mod_php ή άλλης διεπαφής.
3. Η PHP ελέγχει όρια όπως το `post_max_size` και διαχωρίζει το περιεχόμενο με βάση μια ακολουθία διαχωρισμού, το λεγόμενο boundary.
4. Τα κανονικά πεδία καταλήγουν στο `$_POST`, τα τμήματα αρχείων γράφονται σε προσωρινά αρχεία και περιγράφονται στο `$_FILES`.
5. Μόνο τώρα ξεκινά το σενάριο, ελέγχει το αρχείο και το μετακινεί στον προορισμό του.
6. Στο τέλος του αιτήματος η PHP διαγράφει όλα τα προσωρινά αρχεία που δεν μετακινήθηκαν.

## multipart/form-data: η δομή ενός αιτήματος μεταφόρτωσης

Ένα αίτημα μεταφόρτωσης είναι απλό κείμενο με ενσωματωμένα δεδομένα αρχείων. Η κεφαλίδα `Content-Type` δηλώνει το boundary και στο περιεχόμενο αυτή η ακολουθία χαρακτήρων διαχωρίζει τα επιμέρους τμήματα. Κάθε τμήμα έχει δικές του κεφαλίδες με το όνομα του πεδίου και, ενδεχομένως, το όνομα του αρχείου. Ένα έντονα συντομευμένο, αβλαβές παράδειγμα:

```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--
```

Όλα τα στοιχεία αυτού του κειμένου προέρχονται από τον αποστολέα, ακόμη και το όνομα αρχείου και το `Content-Type` του τμήματος. Η PHP τα μεταφέρει στο `$_FILES`, αλλά δεν ελέγχει αν είναι εύλογα.

## Ο πίνακας $_FILES

Για ένα πεδίο με όνομα `lebenslauf`, το `$_FILES['lebenslauf']` περιέχει σύμφωνα με το εγχειρίδιο της PHP τα εξής κλειδιά:

| Κλειδί | Περιεχόμενο | Αξιόπιστο; |
|---|---|---|
| `name` | αρχικό όνομα αρχείου στον αποστολέα | όχι |
| `full_path` | διαδρομή που δηλώνει το πρόγραμμα περιήγησης, από την PHP 8.1.0 | όχι |
| `type` | τύπος MIME σύμφωνα με το πρόγραμμα περιήγησης, δεν ελέγχεται από την PHP | όχι |
| `size` | μέγεθος σε byte | υπολογίζεται από την PHP |
| `tmp_name` | διαδρομή του προσωρινού αρχείου στον διακομιστή | ορίζεται από την PHP |
| `error` | κωδικός σφάλματος της επεξεργασίας της μεταφόρτωσης | ορίζεται από την PHP |

Σε πεδία με αγκύλες στο όνομα, για παράδειγμα `bilder[]`, κάθε κλειδί περιέχει έναν πίνακα με μία εγγραφή ανά αρχείο. Η εφαρμογή διατρέχει τότε, για παράδειγμα, το `$_FILES['bilder']['error']` και προσπελαύνει με τον ίδιο δείκτη τα `tmp_name` και `name`.

Μια φόρμα μπορεί επιπλέον να στείλει ένα κρυφό πεδίο `MAX_FILE_SIZE` πριν από το πεδίο αρχείου. Σύμφωνα με το εγχειρίδιο, πρόκειται μόνο για υπόδειξη προς το πρόγραμμα περιήγησης, η οποία παρακάμπτεται εύκολα. Μπορείτε να βασίζεστε αποκλειστικά στα όρια που επιβάλλει ο διακομιστής: στην PHP, στον διακομιστή ιστού και στην ίδια την εφαρμογή.

## Όρια: οι οδηγίες php.ini για τις μεταφορτώσεις

Αυτές οι οδηγίες ελέγχουν την επεξεργασία των μεταφορτώσεων. Οι προεπιλεγμένες τιμές προέρχονται από το εγχειρίδιο της PHP και ισχύουν όταν δεν τις παρακάμπτει κάποιο php.ini.

| Οδηγία | Προεπιλογή | Τροποποιήσιμη σε |
|---|---|---|
| `file_uploads` | `1` | μόνο στη διαμόρφωση συστήματος |
| `upload_tmp_dir` | κενό (προσωρινός κατάλογος συστήματος) | μόνο στη διαμόρφωση συστήματος |
| `upload_max_filesize` | `2M` | php.ini, pool, διαμόρφωση καταλόγου |
| `post_max_size` | `8M` | php.ini, pool, διαμόρφωση καταλόγου |
| `max_file_uploads` | `20` | php.ini, pool, διαμόρφωση καταλόγου |
| `enable_post_data_reading` | `1` | php.ini, pool, διαμόρφωση καταλόγου |

Το `post_max_size` πρέπει να είναι μεγαλύτερο από το `upload_max_filesize` και το `memory_limit` πρέπει σύμφωνα με το εγχειρίδιο, κατά κανόνα, να είναι μεγαλύτερο από το `post_max_size`. Αν ο κατάλογος `upload_tmp_dir` δεν είναι εγγράψιμος, η PHP καταφεύγει στον προσωρινό κατάλογο του συστήματος. Με το `open_basedir` πρέπει να επιτρέπεται ο προσωρινός κατάλογος, διαφορετικά οι μεταφορτώσεις αποτυγχάνουν. Τιμές που χρησιμοποιούνται στην πράξη και τις συνέπειές τους περιγράφει το άρθρο [Λογικός περιορισμός των post_max_size και upload_max_filesize](https://phpsos.de/el/blog/post-max-size-upload-limits/).

## Σωστή αξιολόγηση των κωδικών σφάλματος

Το πεδίο `error` δείχνει τι συνέβη κατά την επεξεργασία. Οι σταθερές εκτείνονται από το `UPLOAD_ERR_OK` (0) μέσω των `UPLOAD_ERR_INI_SIZE` (1), `UPLOAD_ERR_FORM_SIZE` (2), `UPLOAD_ERR_PARTIAL` (3) και `UPLOAD_ERR_NO_FILE` (4) ως τα `UPLOAD_ERR_NO_TMP_DIR` (6), `UPLOAD_ERR_CANT_WRITE` (7) και `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);
}
```

Το παράδειγμα δείχνει μόνο τον μηχανισμό. Τον έλεγχο του τύπου αρχείου, την αποθήκευση εκτός του webroot και τον αποκλεισμό της εκτέλεσης σεναρίων περιγράφει ο οδηγός [Ασφαλής υλοποίηση μεταφόρτωσης αρχείων στην PHP](https://phpsos.de/el/ratgeber/datei-upload-sicher/).

## Μεταφορτώσεις και PHP2Shell: τι σημαίνουν τα προσωρινά μέτρα

Οι ευπάθειες CVE-2026-109618 και CVE-2026-109619 του PHP2Shell αφορούν την επεξεργασία γύρω από το αίτημα στον διερμηνέα της PHP. Γι' αυτό το php.net αναφέρει ως προσωρινά μέτρα, μεταξύ άλλων, `post_max_size = 8M` (χωρίς μεταφορτώσεις) ή `32M` (με μεταφορτώσεις), `upload_max_filesize` χαμηλότερα, καθώς και `session.upload_progress.enabled=0`. Αυτές οι τιμές ανήκουν στο php.ini, στο pool του FPM ή στη διαμόρφωση του διακομιστή και στη συνέχεια πρέπει να γίνει επανεκκίνηση όλων των workers.

Επιπλέον, ειδικοί συγγραφείς προτείνουν να αποκλείονται τα αιτήματα `multipart/form-data` εκτός των πραγματικών διαδρομών μεταφόρτωσης, στον proxy ή στο WAF. Πρόκειται για ανεπίσημο μέτρο, με τον κίνδυνο να σπάσουν φόρμες· τη στάθμιση περιγράφει το άρθρο [Φιλτράρισμα αιτημάτων μεταφόρτωσης στην άκρη](https://phpsos.de/el/blog/upload-anfragen-am-rand-filtern/). Κανένα από αυτά τα μέτρα δεν αντικαθιστά την ενημέρωση στην PHP 8.5.12, 8.4.27, 8.3.36 ή 8.2.35.

## Πώς βοηθά συγκεκριμένα η PHP SOS;

- Εντοπίζουμε ποιοι από τους ιστότοπούς σας χρειάζονται πράγματι μεταφορτώσεις και σε ποιες διαδρομές.
- Ορίζουμε τα όρια και τα προσωρινά μέτρα ανά pool, επανεκκινούμε όλους τους workers και δοκιμάζουμε τις φόρμες.
- Ελέγχουμε τους καταλόγους μεταφόρτωσης για εκτελέσιμα αρχεία και αποκλείουμε την εκτέλεση σεναρίων στο πλαίσιο της [θωράκισης διακομιστή](https://phpsos.de/el/leistungen/server-haertung/).
- Εγκαθιστούμε την ενημέρωση της PHP και τεκμηριώνουμε το επίπεδο ενημέρωσης ανά ιστότοπο.


## Συχνές ερωτήσεις

**Πού αποθηκεύει η PHP αρχικά τα αρχεία που μεταφορτώνονται;**  
Σε έναν προσωρινό κατάλογο. Από προεπιλογή είναι ο προσωρινός κατάλογος του συστήματος· με το upload_tmp_dir μπορεί να αλλάξει. Αν το αρχείο δεν μετακινηθεί μέσα στο σενάριο, η PHP το διαγράφει στο τέλος του αιτήματος.

**Μπορώ να εμπιστεύομαι το πεδίο type του $_FILES;**  
Όχι. Τον τύπο MIME τον δηλώνει το πρόγραμμα περιήγησης και σύμφωνα με το εγχειρίδιο η PHP δεν τον ελέγχει. Και τα name και full_path προέρχονται από τον αποστολέα. Τον πραγματικό τύπο του αρχείου τον προσδιορίζετε στην πλευρά του διακομιστή με βάση το περιεχόμενο.

**Γιατί το $_FILES είναι άδειο, ενώ στάλθηκε αρχείο;**  
Συνήθως ολόκληρο το αίτημα ήταν μεγαλύτερο από το post_max_size. Τότε η PHP αδειάζει πλήρως τα $_POST και $_FILES, χωρίς κωδικό σφάλματος στον πίνακα. Άλλες αιτίες είναι ένα enctype που λείπει από τη φόρμα ή απενεργοποιημένα file_uploads.

**Βοηθά κατά του PHP2Shell η απαγόρευση των μεταφορτώσεων στην εφαρμογή;**  
Όχι. Η επεξεργασία των δεδομένων του αιτήματος γίνεται στην PHP, πριν εκτελεστεί ο κώδικας της εφαρμογής. Αποτελεσματικά είναι η ενημέρωση της PHP και η επανεκκίνηση όλων των workers· τα στενότερα όρια αποτελούν μόνο προσωρινό μέτρο.

**Ποια είναι η διαφορά μεταξύ upload_max_filesize και post_max_size;**  
Το upload_max_filesize περιορίζει κάθε μεμονωμένο αρχείο, ενώ το post_max_size ολόκληρο το περιεχόμενο του αιτήματος, μαζί με όλα τα αρχεία και τα πεδία. Γι' αυτό το post_max_size πρέπει να είναι μεγαλύτερο από το upload_max_filesize.

## Πηγές

- [Εγχειρίδιο PHP: Μεταφορτώσεις με POST](https://www.php.net/manual/de/features.file-upload.post-method.php)
- [Εγχειρίδιο PHP: Μηνύματα σφάλματος στις μεταφορτώσεις](https://www.php.net/manual/de/features.file-upload.errors.php)
- [Εγχειρίδιο PHP: Οδηγίες php.ini](https://www.php.net/manual/de/ini.core.php)
- [php.net: Δελτία ασφαλείας](https://www.php.net/)
