PHP move_uploaded_file 函数
最后修改于 2025 年 4 月 3 日
PHP move_uploaded_file 函数将上传的文件移动到新位置。它对于在 Web 应用程序中安全地处理文件上传至关重要。
基本定义
move_uploaded_file 函数将上传的文件移动到指定的目标位置。出于安全考虑,它会检查文件是否是通过 HTTP POST 上传的。
语法:move_uploaded_file(string $from, string $to): bool。成功时返回 true,失败时返回 false。该函数确保文件处理安全。
基本文件上传示例
这展示了一个完整的文件上传表单以及使用 move_uploaded_file 进行处理。
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadDir = 'uploads/';
$uploadFile = $uploadDir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadFile)) {
echo "File uploaded successfully.";
} else {
echo "File upload failed.";
}
}
?>
<form enctype="multipart/form-data" method="POST">
<input type="file" name="userfile">
<button type="submit">Upload</button>
</form>
此示例展示了一个完整的文件上传过程。表单提交给自己,如果上传成功,PHP 会移动文件。在处理之前,请务必检查请求方法。
带验证的安全文件上传
此示例在移动上传的文件之前添加了安全检查。
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadDir = 'uploads/';
$allowedTypes = ['image/jpeg', 'image/png'];
$maxSize = 2 * 1024 * 1024; // 2MB
$file = $_FILES['userfile'];
if (!in_array($file['type'], $allowedTypes)) {
die("Invalid file type.");
}
if ($file['size'] > $maxSize) {
die("File too large.");
}
$filename = uniqid() . '_' . basename($file['name']);
$uploadFile = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
echo "File uploaded securely.";
} else {
echo "Upload failed.";
}
}
?>
这增加了类型检查、大小限制和文件名清理。使用 uniqid() 可防止文件名冲突。在处理上传之前,请务必验证它们。
多个文件上传
在循环中使用 move_uploaded_file 处理多个文件上传。
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadDir = 'uploads/';
foreach ($_FILES['userfiles']['tmp_name'] as $key => $tmpName) {
if ($_FILES['userfiles']['error'][$key] !== UPLOAD_ERR_OK) {
continue;
}
$filename = basename($_FILES['userfiles']['name'][$key]);
$uploadFile = $uploadDir . $filename;
if (move_uploaded_file($tmpName, $uploadFile)) {
echo "File {$filename} uploaded.<br>";
}
}
}
?>
<form enctype="multipart/form-data" method="POST">
<input type="file" name="userfiles[]" multiple>
<button type="submit">Upload</button>
</form>
这可以一次处理多个上传的文件。表单在输入名称和 multiple 属性中使用数组表示法。每个文件都单独处理。
自定义目标文件名
在保持安全性的同时为上传的文件创建自定义文件名。
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadDir = 'uploads/';
$file = $_FILES['userfile'];
// Get file extension
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
// Generate safe filename
$filename = 'user_upload_' . time() . '.' . $ext;
$uploadFile = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
echo "File saved as {$filename}";
}
}
?>
这会在保留原始扩展名的同时生成自定义文件名。time() 函数有助于创建唯一名称。始终保留文件扩展名以便正确处理。
错误处理和报告
对使用 move_uploaded_file 进行的文件上传操作进行适当的错误处理。
<?php
declare(strict_types=1);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadDir = 'uploads/';
if (!is_dir($uploadDir) && !mkdir($uploadDir, 0755, true)) {
die("Cannot create upload directory.");
}
if (!is_writable($uploadDir)) {
die("Upload directory not writable.");
}
$file = $_FILES['userfile'];
switch ($file['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
die("File too large.");
default:
die("Upload error.");
}
$uploadFile = $uploadDir . basename($file['name']);
if (!move_uploaded_file($file['tmp_name'], $uploadFile)) {
die("Failed to move uploaded file.");
}
echo "Upload successful.";
}
?>
此示例检查目录权限并处理各种上传错误。它在尝试移动文件之前验证上传目录是否存在且可写。全面的错误处理可防止安全问题。
最佳实践
- 验证输入:检查文件类型、大小和名称。
- 安全存储:如果可能,将上传的文件存储在 Web 根目录之外。
- 权限:设置正确的目录权限 (0755)。
- 错误处理:处理所有可能的上传错误。
- 文件名安全:为存储生成安全的文件名。
来源
本教程通过实际示例涵盖了 PHP move_uploaded_file 函数,展示了在不同场景下安全的文件上传处理。
作者
列出 所有 PHP 文件系统函数。