Is uploaded file: примеры (PHP)
is_uploaded_file(string $filename): boolФункция is_uploaded_file() в PHP проверяет, был ли указанный файл загружен через HTTP POST (например, через форму с атрибутом enctype="multipart/form-data"). Эта проверка является важной мерой безопасности, которая позволяет убедиться, что скрипт работает именно с загруженным пользователем файлом, а не с локальным файлом, путь к которому мог быть подделан.
Функция используется в процессе обработки загруженных файлов, обычно перед перемещением файла из временного каталога в постоянное место назначения с помощью функции move_uploaded_file().
Функция принимает один обязательный аргумент:
string $filename- путь к проверяемому файлу. Обычно это значение элемента$_FILES['userfile']['tmp_name'].
Возвращаемое значение: bool - true, если файл был загружен через HTTP POST, и false в противном случае.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$tmpFile = $_FILES['avatar']['tmp_name'];
if (is_uploaded_file($tmpFile)) {
echo "Файл был корректно загружен через POST.";
} else {
echo "Файл не был загружен через POST.";
}
}
?>// Если файл загружен через форму: Файл был корректно загружен через POST. // Если переменная $tmpFile указывает на локальный файл, например, '/etc/passwd': Файл не был загружен через POST.
<?php
if (isset($_FILES['document'])) {
$uploadDir = 'uploads/';
$tmpName = $_FILES['document']['tmp_name'];
$finalName = $uploadDir . basename($_FILES['document']['name']);
if (is_uploaded_file($tmpName)) {
if (move_uploaded_file($tmpName, $finalName)) {
echo "Файл успешно загружен и перемещен.";
} else {
echo "Ошибка перемещения файла.";
}
} else {
echo "Возможная атака: файл не был загружен через POST.";
}
}
?>move_uploaded_file() - не только проверяет, был ли файл загружен через POST, но и безопасно перемещает его в новое место. Это предпочтительная функция для финального сохранения загруженного файла, так как она включает в себя внутреннюю проверку is_uploaded_file(). Использовать is_uploaded_file() отдельно имеет смысл, если нужна только проверка без немедленного перемещения, либо для дополнительного логирования.
file_exists() - проверяет существование файла или каталога на диске, но не проверяет его происхождение. Она не является безопасной заменой, так как вернет true для любого существующего локального файла.
В Python нет прямой аналогии, так как фреймворки сами управляют загруженными файлами. Файл становится доступен только после прохождения валидации фреймворком.
from flask import Flask, request, flash
import os
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# Файл, полученный через request.files, уже является объектом загрузки
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file:
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return 'File uploaded successfully'
В Node.js middleware Multer обрабатывает загрузку файлов, и проверка на «загруженность» осуществляется самим middleware до передачи файла в роут.
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const app = express();
app.post('/profile', upload.single('avatar'), (req, res) => {
// Файл в req.file доступен только если Multer успешно его загрузил
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
res.send('File uploaded!');
});
В отличие от PHP, где разработчик должен явно вызвать проверку, в этих языках и фреймворках валидация происхождения файла инкапсулирована в механизме обработки запросов.
<?php
// ОШИБКА: Передается имя файла, а не временный путь.
if (is_uploaded_file($_FILES['file']['name'])) { // Неправильно
// ...
}
// ПРАВИЛЬНО: Передается временный путь к файлу.
if (is_uploaded_file($_FILES['file']['tmp_name'])) { // Правильно
// ...
}
?><?php
// ОШИБКА: Проверка без предварительного анализа ошибки загрузки.
if (is_uploaded_file($_FILES['file']['tmp_name'])) {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/file.txt');
}
// Если $_FILES['file']['error'] !== UPLOAD_ERR_OK, файл может быть не загружен.
// ПРАВИЛЬНО: Сначала проверяем код ошибки.
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
if (is_uploaded_file($_FILES['file']['tmp_name'])) {
// ...
}
}
?><?php
move_uploaded_file($tmpFile, $destination);
// ОШИБКА: Проверка после перемещения. Файла во временном каталоге уже нет.
if (is_uploaded_file($tmpFile)) { // Всегда false
echo "Этот код никогда не выполнится.";
}
?>Поведение функции is_uploaded_file() оставалось стабильным на протяжении многих версий PHP. В PHP 8.0 не было внесено значительных изменений, влияющих на ее работу. Основной принцип проверки файлов, загруженных через HTTP POST, не менялся с версии PHP 4.0.3. Всегда важно учитывать, что функция работает в связке с настройками php.ini, такими как file_uploads, upload_tmp_dir, upload_max_filesize и max_file_uploads.
<?php
if (!empty($_FILES['images']['name'][0])) {
$uploadDir = 'uploads/';
foreach ($_FILES['images']['tmp_name'] as $key => $tmpName) {
// Проверяем каждый файл на ошибку загрузки
if ($_FILES['images']['error'][$key] !== UPLOAD_ERR_OK) {
echo "Ошибка загрузки файла {$_FILES['images']['name'][$key]}
";
continue;
}
// Проверяем, что файл действительно загружен через POST
if (is_uploaded_file($tmpName)) {
$safeName = $uploadDir . basename($_FILES['images']['name'][$key]);
if (move_uploaded_file($tmpName, $safeName)) {
echo "Файл {$_FILES['images']['name'][$key]} успешно сохранен.
";
}
} else {
echo "Файл {$_FILES['images']['name'][$key]} не прошел проверку безопасности.
";
}
}
}
?><?php
$tmpFile = $_FILES['report']['tmp_name'];
$logFile = 'security.log';
if (!is_uploaded_file($tmpFile)) {
$message = date('Y-m-d H:i:s') .
" | Попытка обработки не загруженного файла: " .
htmlspecialchars($tmpFile) . PHP_EOL;
file_put_contents($logFile, $message, FILE_APPEND);
die("Ошибка безопасности: недопустимый источник файла.");
}
// ... дальнейшая обработка безопасного файла
?><?php
$tmpFile = $_FILES['config']['tmp_name'];
if (is_uploaded_file($tmpFile)) {
// Можно безопасно получить MIME-тип для дополнительной валидации
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmpFile);
finfo_close($finfo);
$allowedMimes = ['text/plain', 'application/json'];
if (in_array($mime, $allowedMimes)) {
// Чтение содержимого для анализа
$content = file_get_contents($tmpFile);
echo "Содержимое файла безопасно для обработки.";
} else {
echo "Запрещенный тип файла.";
}
}
?>