Move uploaded file: примеры (PHP)
move_uploaded_file(string $from, string $to): boolФункция move_uploaded_file() является частью PHP и предназначена для безопасного перемещения файла, загруженного через HTTP POST.
Эта функция проверяет, является ли указанный файл действительно загруженным через механизм загрузки PHP (т.е. через форму с enctype='multipart/form-data'). Только после успешной проверки файл перемещается в указанное место. Она используется для сохранения загруженных пользователем файлов на сервере, например, изображений, документов или архивов.
- from (string, обязательный): Временный путь к загруженному файлу, который хранится в глобальном массиве $_FILES['userfile']['tmp_name'].
- to (string, обязательный): Путь назначения, куда файл должен быть перемещен. Должен включать имя файла. Если файл с таким именем уже существует, он будет перезаписан.
Код для обработки загруженного файла с именем 'avatar':
<?php
if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['avatar']['tmp_name'];
$destination = '/var/www/uploads/' . basename($_FILES['avatar']['name']);
if (move_uploaded_file($tmp_name, $destination)) {
echo "Файл успешно загружен.";
} else {
echo "Не удалось переместить файл.";
}
}
?>Результат при успехе: Файл успешно загружен. Результат при неудаче (например, если файл не был загружен через POST): Не удалось переместить файл.
<?php
$upload_dir = 'uploads/';
$original_name = $_FILES['document']['name'];
$extension = pathinfo($original_name, PATHINFO_EXTENSION);
$new_filename = uniqid('doc_') . '.' . $extension;
$destination = $upload_dir . $new_filename;
if (move_uploaded_file($_FILES['document']['tmp_name'], $destination)) {
echo "Файл сохранен как: " . htmlspecialchars($new_filename);
}
?>Результат: Файл сохранен как: doc_5f2a1b3c4d5e6.pdf
- copy(): Копирует файл. Не проверяет, был ли файл загружен через HTTP POST. Используется для копирования любых существующих файлов на сервере.
- rename(): Переименовывает или перемещает файл. Также не выполняет проверок на безопасность загрузки. Подходит для работы с локальными файлами файловой системы.
- is_uploaded_file(): Проверяет, был ли файл загружен через HTTP POST. Эта проверка встроена в move_uploaded_file(). Её можно использовать отдельно для дополнительной валидации перед другими операциями.
Функция move_uploaded_file() является предпочтительной именно для сохранения загруженных пользователем файлов из-за встроенной проверки безопасности. copy() или rename() применяют для внутренних операций с файлами сервера.
from flask import Flask, request
import os
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return 'No file part'
file = request.files['file']
if file.filename == '':
return 'No selected file'
if file:
filename = os.path.join('uploads', file.filename)
file.save(filename)
return 'File uploaded successfully'
Метод .save() объекта файла сохраняет его на диск. Проверки выполняются вручную.
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const app = express();
app.post('/upload', upload.single('avatar'), (req, res) => {
// Файл уже сохранен в 'uploads/' с временным именем.
// Дальнейшая обработка, например, переименование.
res.send('File uploaded!');
});Middleware multer автоматически обрабатывает загрузку и сохраняет файл в указанную директорию.
В PHP функция move_uploaded_file() совмещает проверку и перемещение. В других языках эти этапы часто разделены: сначала промежуточное ПО или библиотека валидирует загрузку, а затем файл сохраняется стандартными средствами работы с файловой системой.
<?php
// ОШИБКА: Не проверяется $_FILES['file']['error']
$tmp_name = $_FILES['file']['tmp_name'];
move_uploaded_file($tmp_name, 'uploads/file.txt'); // Может потерпеть неудачу
?>Если загрузка изначально не удалась (например, превышен размер), то move_uploaded_file вернет false, а исходный файл может не существовать.
<?php
// ОШИБКА: Директория 'my_uploads' может не существовать
move_uploaded_file($_FILES['img']['tmp_name'], 'my_uploads/new.jpg');
?>Функция вернет false, и в логах ошибок появится предупреждение.
<?php
// ОШИБКА: Использование оригинального имени без проверки
$dest = 'uploads/' . $_FILES['file']['name']; // Может содержать '../' или опасные символы
move_uploaded_file($_FILES['file']['tmp_name'], $dest);
?>Это может привести к перезаписи системных файлов или сохранению файлов за пределами целевой директории.
Всегда проверяйте код ошибки $_FILES['...']['error'], создавайте целевую директорию при необходимости с помощью is_dir() и mkdir(), а также генерируйте безопасное имя файла.
Поведение функции move_uploaded_file() остается стабильным. В PHP 8.0 повысилась строгость типов, но сигнатура функции не изменилась: оба аргумента по-прежнему ожидают строку (string).
- В PHP 8.0, если передать аргумент нестрокового типа, будет вызвана ошибка TypeError. В более ранних версиях PHP могло произойти автоматическое приведение к строке.
- Критических изменений в логике работы функции в последних основных версиях (PHP 7.4, 8.0, 8.1, 8.2, 8.3) не было.
Важно отметить, что общие настройки, связанные с загрузкой файлов (такие как upload_max_filesize, post_max_size и file_uploads), могут влиять на доступность функции.
<?php
if (is_uploaded_file($_FILES['photo']['tmp_name'])) {
$tmp_path = $_FILES['photo']['tmp_name'];
$img_info = getimagesize($tmp_path);
if ($img_info && $img_info['mime'] == 'image/jpeg') {
$image = imagecreatefromjpeg($tmp_path);
$thumb = imagescale($image, 150);
imagedestroy($image);
$dest_path = 'uploads/thumb_' . time() . '.jpg';
// Сохраняем миниатюру
imagejpeg($thumb, $dest_path);
imagedestroy($thumb);
// Оригинал тоже можно переместить
move_uploaded_file($tmp_path, 'uploads/fullsize/' . $_FILES['photo']['name']);
echo "Изображение обработано и сохранено.";
}
}
?>Создается миниатюра изображения, а оригинальный файл сохраняется в отдельной папке.
<?php
$allowed_types = ['application/pdf', 'image/png'];
$upload_dir = 'docs/';
foreach ($_FILES['documents']['tmp_name'] as $key => $tmp_name) {
$file_type = mime_content_type($tmp_name);
if (!in_array($file_type, $allowed_types)) {
continue; // Пропускаем неразрешенные типы
}
$safe_name = md5_file($tmp_name) . '_' . basename($_FILES['documents']['name'][$key]);
$destination = $upload_dir . $safe_name;
move_uploaded_file($tmp_name, $destination);
}
echo "Разрешенные файлы загружены.";
?>Файлы проверяются по реальному MIME-типу и сохраняются с именем, включающим хэш содержимого для уникальности.
<?php
function log_upload($filename, $success) {
$log_entry = date('Y-m-d H:i:s') . ' - ' . $filename . ' - ' . ($success ? 'SUCCESS' : 'FAIL') . PHP_EOL;
file_put_contents('upload.log', $log_entry, FILE_APPEND);
}
$dest = 'files/' . $_FILES['report']['name'];
if (move_uploaded_file($_FILES['report']['tmp_name'], $dest)) {
log_upload($_FILES['report']['name'], true);
} else {
log_upload($_FILES['report']['name'], false);
}
?>Каждая попытка загрузки записывается в лог-файл с указанием времени, имени файла и статуса.