ZetCode

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 进行处理。

basic_upload.php
<?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 会移动文件。在处理之前,请务必检查请求方法。

带验证的安全文件上传

此示例在移动上传的文件之前添加了安全检查。

secure_upload.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 处理多个文件上传。

multi_upload.php
<?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 属性中使用数组表示法。每个文件都单独处理。

自定义目标文件名

在保持安全性的同时为上传的文件创建自定义文件名。

custom_filename.php
<?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 进行的文件上传操作进行适当的错误处理。

error_handling.php
<?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.";
}
?>

此示例检查目录权限并处理各种上传错误。它在尝试移动文件之前验证上传目录是否存在且可写。全面的错误处理可防止安全问题。

最佳实践

来源

PHP move_uploaded_file 文档

本教程通过实际示例涵盖了 PHP move_uploaded_file 函数,展示了在不同场景下安全的文件上传处理。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 PHP 文件系统函数