Skip to content

13.1 文件上传表单

文件上传是 Web 应用中常见的功能,如上传头像、上传图片、上传文档等。本章节将介绍如何创建文件上传表单。

基本原理

文件上传的基本流程:

  1. 创建包含 enctype="multipart/form-data" 的表单
  2. 添加 <input type="file"> 元素
  3. 服务器接收并处理上传的文件

创建文件上传表单

基本表单

html
<!DOCTYPE html>
<html>
<head>
    <title>文件上传</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 500px; margin: 0 auto; padding: 20px; }
        h1 { text-align: center; color: #333; }
        .form-group { margin: 15px 0; }
        label { display: block; margin-bottom: 5px; font-weight: bold; }
        input[type="file"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; width: 100%; box-sizing: border-box; }
        input[type="submit"] { padding: 10px 20px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }
        .message { padding: 10px; margin: 10px 0; border-radius: 4px; }
        .success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
    </style>
</head>
<body>
    <h1>文件上传</h1>
    
    <?php if (isset($_GET['success'])): ?>
        <div class="message success">
            <?php echo $_GET['success']; ?>
        </div>
    <?php endif; ?>
    
    <?php if (isset($_GET['error'])): ?>
        <div class="message error">
            <?php echo $_GET['error']; ?>
        </div>
    <?php endif; ?>
    
    <form action="upload.php" method="post" enctype="multipart/form-data">
        <div class="form-group">
            <label>选择文件: <input type="file" name="fileToUpload" id="fileToUpload"></label>
        </div>
        <input type="submit" value="上传文件" name="submit">
    </form>
</body>
</html>

多文件上传

html
<!DOCTYPE html>
<html>
<head>
    <title>多文件上传</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 500px; margin: 0 auto; padding: 20px; }
        h1 { text-align: center; color: #333; }
        .form-group { margin: 15px 0; }
        label { display: block; margin-bottom: 5px; font-weight: bold; }
        input[type="file"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; width: 100%; box-sizing: border-box; margin-bottom: 10px; }
        input[type="submit"] { padding: 10px 20px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }
    </style>
</head>
<body>
    <h1>多文件上传</h1>
    
    <form action="upload_multiple.php" method="post" enctype="multipart/form-data">
        <div class="form-group">
            <label>选择文件 1: <input type="file" name="files[]"></label>
            <label>选择文件 2: <input type="file" name="files[]"></label>
            <label>选择文件 3: <input type="file" name="files[]"></label>
        </div>
        <input type="submit" value="上传文件" name="submit">
    </form>
</body>
</html>

带额外字段的表单

html
<!DOCTYPE html>
<html>
<head>
    <title>带额外字段的文件上传</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 500px; margin: 0 auto; padding: 20px; }
        h1 { text-align: center; color: #333; }
        .form-group { margin: 15px 0; }
        label { display: block; margin-bottom: 5px; font-weight: bold; }
        input[type="text"], input[type="file"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; width: 100%; box-sizing: border-box; }
        input[type="submit"] { padding: 10px 20px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }
    </style>
</head>
<body>
    <h1>带额外字段的文件上传</h1>
    
    <form action="upload_with_fields.php" method="post" enctype="multipart/form-data">
        <div class="form-group">
            <label>文件名: <input type="text" name="fileName"></label>
        </div>
        <div class="form-group">
            <label>文件描述: <input type="text" name="fileDescription"></label>
        </div>
        <div class="form-group">
            <label>选择文件: <input type="file" name="fileToUpload"></label>
        </div>
        <input type="submit" value="上传文件" name="submit">
    </form>
</body>
</html>

表单属性说明

1. enctype 属性

必须设置 enctype="multipart/form-data",否则文件无法上传。

2. method 属性

必须使用 method="post",因为文件上传需要发送大量数据。

3. input type="file"

  • name 属性:用于在服务器端获取文件
  • id 属性:用于关联 label
  • multiple 属性:允许选择多个文件
  • accept 属性:限制文件类型

4. accept 属性

限制可选择的文件类型:

html
<!-- 只允许图片文件 -->
<input type="file" name="fileToUpload" accept="image/*">

<!-- 只允许特定图片类型 -->
<input type="file" name="fileToUpload" accept=".jpg,.jpeg,.png,.gif">

<!-- 只允许 PDF 文件 -->
<input type="file" name="fileToUpload" accept=".pdf">

5. multiple 属性

允许选择多个文件:

html
<input type="file" name="files[]" multiple>

服务器端处理

基本处理

php
<?php
// upload.php
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));

// 检查文件是否是真实的图片
if(isset($_POST["submit"])) {
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) {
        echo "文件是一个图片 - " . $check["mime"] . ".";
        $uploadOk = 1;
    } else {
        echo "文件不是一个图片.";
        $uploadOk = 0;
    }
}

// 检查文件是否已存在
if (file_exists($target_file)) {
    echo "抱歉,文件已存在.";
    $uploadOk = 0;
}

// 检查文件大小
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "抱歉,你的文件太大了.";
    $uploadOk = 0;
}

// 允许的文件格式
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
    echo "抱歉,只允许 JPG, JPEG, PNG & GIF 文件.";
    $uploadOk = 0;
}

// 检查 $uploadOk 是否为 0
if ($uploadOk == 0) {
    echo "抱歉,你的文件没有上传.";
// 如果一切正常,尝试上传文件
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
        echo "文件 " . htmlspecialchars( basename( $_FILES["fileToUpload"]["name"]). " 已成功上传.";
    } else {
        echo "抱歉,上传文件时出错.";
    }
}
?>

多文件处理

php
<?php
// upload_multiple.php
$target_dir = "uploads/";
$uploadOk = 1;

if(isset($_POST["submit"])) {
    foreach ($_FILES["files"]["name"] as $key => $name) {
        $target_file = $target_dir . basename($name);
        $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
        
        // 检查文件是否是真实的图片
        $check = getimagesize($_FILES["files"]["tmp_name"][$key]);
        if($check !== false) {
            echo "文件 " . $name . " 是一个图片 - " . $check["mime"] . ".<br>";
            $uploadOk = 1;
        } else {
            echo "文件 " . $name . " 不是一个图片.<br>";
            $uploadOk = 0;
        }
        
        // 检查文件大小
        if ($_FILES["files"]["size"][$key] > 500000) {
            echo "抱歉,文件 " . $name . " 太大了.<br>";
            $uploadOk = 0;
        }
        
        // 允许的文件格式
        if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
        && $imageFileType != "gif" ) {
            echo "抱歉,文件 " . $name . " 类型不允许.<br>";
            $uploadOk = 0;
        }
        
        // 尝试上传文件
        if ($uploadOk == 1) {
            if (move_uploaded_file($_FILES["files"]["tmp_name"][$key], $target_file)) {
                echo "文件 " . htmlspecialchars( basename( $name)). " 已成功上传.<br>";
            } else {
                echo "抱歉,上传文件 " . $name . " 时出错.<br>";
            }
        }
    }
}
?>

注意事项

  1. 创建上传目录:确保 uploads 目录存在且具有写入权限
  2. 文件验证:验证文件类型、大小、是否为真实图片等
  3. 安全处理
    • 重命名文件,避免文件名冲突
    • 防止恶意文件上传
    • 限制上传文件的大小和类型
  4. 错误处理:提供清晰的错误提示
  5. 文件存储:考虑使用唯一文件名存储文件

练习

  1. 创建一个基本的文件上传表单
  2. 创建一个多文件上传表单
  3. 实现文件类型和大小的验证
  4. 实现文件重命名功能
  5. 显示上传成功的文件

© 2026 编程马·菜鸟教程 版权所有