【问题标题】:What's the best way to create a single-file upload form using PHP?使用 PHP 创建单文件上传表单的最佳方法是什么?
【发布时间】:2010-09-16 22:26:12
【问题描述】:

我在网上找到了一些示例,但我想从每天使用 PHP 的人那里获得有关潜在安全性或性能注意事项及其解决方案的反馈。

请注意,我只对一次上传一个文件感兴趣。

理想情况下不需要浏览器插件(Flash/Java),但了解使用插件的好处会很有趣。

我想知道最好的HTML表单代码和PHP处理代码。

【问题讨论】:

    标签: php upload file-upload


    【解决方案1】:

    文件上传教程

    HTML

    <form enctype="multipart/form-data" action="action.php" method="POST">
      <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
      <input name="userfile" type="file" />
      <input type="submit" value="Go" />
    </form>
    
    • action.php 是将处理上传的 PHP 文件的名称(如下所示)
    • MAX_FILE_SIZE 必须紧接在 file 类型的输入之前。这个值很容易在客户端上被操纵,所以不应该依赖。它的主要好处是在用户上传文件之前,向用户提供文件太大的早期警告。
    • 您可以使用file 类型更改输入的名称,但请确保它不包含任何空格。您还必须更新 PHP 文件(如下)中的相应值。

    PHP

    <?php
    $uploaddir = "/www/uploads/";
    $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
    
    echo '<pre>';
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
        echo "Success.\n";
    } else {
        echo "Failure.\n";
    }
    
    echo 'Here is some more debugging info:';
    print_r($_FILES);
    print "</pre>";
    ?>
    

    upload-to 文件夹不应位于可通过 HTTP 访问的位置,否则可能会上传 PHP 脚本并在服务器上执行。

    打印$_FILES 的值可以提示正在发生的事情。例如:

    大批 ( [用户文件] => 数组 ( [名称] => 文件名.ext [类型] => [tmp_name] => [错误] => 2 [大小] => 0 ) )

    这个结构提供了一些关于文件名、MIME 类型、大小和错误代码的信息。

    错误代码

    0 表示没有错误,文件已成功上传
    1 表示文件超过了 php.ini 中定义的最大文件大小。如果您想更改最大文件大小,您需要打开您的 php.ini 文件,确定显示为:upload_max_filesize = 2M 的行并将值从 2M (2MB) 更改为您需要的任何值
    2 表示已超出页面脚本中手动定义的最大文件大小
    3 表示文件只上传了部分
    4 表示尚未指定文件(空文件字段)
    5 尚未定义
    6 表示没有临时文件夹
    7 表示文件无法写入磁盘

    php.ini配置

    使用较大的文件运行此设置时,您可能会收到错误。检查您的 php.ini 文件以获取这些密钥:

    max_execution_time = 30
    upload_max_filesize = 2M

    适当增加这些值可能会有所帮助。使用 Apache 时,对此文件的更改需要重新启动。

    最大内存允许值(通过memory_limit 设置)在此处不起作用,因为文件在上传时被写入 tmp 目录。 tmp 目录的位置可以通过upload_tmp_dir 控制。

    检查文件 mimetypes

    您应该检查用户上传的文件类型 - 最佳做法是根据允许的文件类型列表进行验证。允许任何文件的潜在风险是用户可能会将 PHP 代码上传到服务器然后运行它

    您可以使用非常有用的 fileinfo 扩展(取代旧的 mime_content_type 函数)来验证 mime 类型。

    // FILEINFO_MIME set to return MIME types, will return string of info otherwise
    $fileinfo = new finfo(FILEINFO_MIME);
    $file = $fileinfo->file($_FILE['filename']);
    
    $allowed_types = array('image/jpeg', 'image/png');
    if(!in_array($file, $allowed_types))
    {
        die('Files of type' . $file . ' are not allowed to be uploaded.');
    }
    // Continue
    

    更多信息

    您可以在PHP.net manual 阅读有关处理文件上传的更多信息。

    对于 PHP 5.3+

    //For those who are using PHP 5.3, the code varies.
    $fileinfo = new finfo(FILEINFO_MIME_TYPE);
    $file = $fileinfo->file($_FILE['filename']['tmp_name']);
    $allowed_types = array('image/jpeg', 'image/png');
    if(!in_array($file, $allowed_types))
    {
        die('Files of type' . $file . ' are not allowed to be uploaded.');
    }
    // Continue
    

    更多信息

    您可以在PHP.net documentation 阅读有关 FILEINFO_MIME_TYPE 的更多信息。

    【讨论】:

    • 值得注意的是,在该示例中,我可以上传一个 php 文件并访问您的 Web 服务器。小心那些东西。 :S
    • 没错。我将此作为社区答案发布,因此请随时自行编辑 :)
    • 是的,检查您上传的文件的 mimetype 很重要。最好的保护是允许某些类型(图像/jpeg、存档/zip 等)并禁止所有其他类型。
    • @Ross:这听起来是个好主意。你能演示一些检查 MIME 类型的代码吗?谢谢你的链接,顺便说一句。
    • 我使用 FileInfo 扩展来检查 MIME 类型。添加到这篇文章中(因为它更好)并稍微改变了格式。
    【解决方案2】:

    安全性对于文件上传来说是一件非常重要的事情,向上传文件夹添加一个 .htaccess 可以阻止脚本从中运行,这可以方便地添加额外的安全层。

    .htaccess

    Options -Indexes
    Options -ExecCGI
    AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi 
    

    参考:http://www.mysql-apache-php.com/fileupload-security.htm

    【讨论】:

      【解决方案3】:

      阅读this introduction,它应该会告诉你你需要知道的一切。用户 cmets 也相当有用。

      【讨论】:

        【解决方案4】:

        Flash 的主要好处是它允许您上传多个文件。 Java 的主要好处是它允许从文件系统拖放。很抱歉没有回答中心问题,但我想我会把它扔进去,因为它相当简单。

        【讨论】:

        • 另一个好处是在 PHP 4 中你不能显示上传进度条。您可以在 PHP 5、Flash 和 Java 中使用。
        • 与其讨论 Java 和 Flash,如果您提供的示例代码展示了如何使用 PHP5 显示进度条会更有用;)
        • 可以使用 PHP 支持的 HTML 数组功能上传多个文件。 php manual
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-28
        • 2017-06-22
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        • 2012-01-21
        相关资源
        最近更新 更多