使用 PHP 创建单文件上传表单的最佳方法是啥?
Posted
技术标签:
【中文标题】使用 PHP 创建单文件上传表单的最佳方法是啥?【英文标题】: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处理代码。
【问题讨论】:
【参考方案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
的值可以提示正在发生的事情。例如:
这个结构提供了一些关于文件名、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 显示进度条会更有用;) 你可以。 phpclasses.org/blog/post/… 您可以使用 PHP 支持的 HTML 数组功能上传多个文件。 php manual以上是关于使用 PHP 创建单文件上传表单的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Web 表单通过 HTTP POST 上传文件的最佳方式是啥?
通过表单按钮在 laravel 中触发 php 脚本的最佳方法是啥?
创建单页应用程序 React JS 的最佳方法是啥? [关闭]