使用PHP重命名已上传的文件但保留扩展名

15

我正在使用PHP从表单上传图像到服务器,并希望将图像重命名为lastname_firstname.[原始扩展名]。我目前有:

move_uploaded_file($_FILES["picture"]["tmp_name"], "peopleimages/" . "$_POST[lastname]" . '_' . "$_POST[firstname]")

当然,这会重命名没有扩展名的文件姓_名。我该怎么样才能重命名文件但保留扩展名呢?

谢谢!

7个回答

36
你需要先找出原始的扩展名 ;-)
为了做到这一点,pathinfo 函数可以发挥奇效 ;-)
引用手册中给出的例子:
$path_parts = pathinfo('/www/htdocs/index.html');
echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0

会给你的:
/www/htdocs
index.html
html
index

顺便提一下,不要忘记安全性:

我也使用is_uploaded_file()函数来检查我们指向的文件是否确实是上传的文件。 - Niels Bom
@Niels Bom:move_uploaded_file会自动为您完成。 - zneak

4

您可以尝试以下方法:

move_uploaded_file($_FILES["picture"]["tmp_name"], "peopleimages/" . "$_POST[lastname]" . '_' . "$_POST[firstname]".".".end(explode(".", $_FILES["picture"]["tmp_name"])))

或者像Niels Bom建议的那样

$filename=$_FILES["picture"]["tmp_name"];
$extension=end(explode(".", $filename));
$newfilename="$_POST[lastname]" . '_' . "$_POST[firstname]".".".$extension;
move_uploaded_file($filename, "peopleimages/" .$newfilename);

那是一行很长的代码,大多数编码标准都建议避免这样做,因为可读性差。我建议你遵循它们。 - Niels Bom

4

如果您允许用户上传任意文件而未检查其扩展名,则他们可以完全上传.php文件并在您的服务器上执行代码 ;)

防止在某个文件夹内执行php的.htaccess规则如下(根据您的设置进行调整)。

AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI

把这段代码放到上传文件的文件夹中的.htaccess文件中。 否则,要记住文件名可能会有多个“.”,你就没问题了。

3

这段代码存在安全隐患。

move_uploaded_file($_FILES["picture"]["tmp_name"], "peopleimages/" . "$_POST[lastname]" . '_' . "$_POST[firstname]". $extension);

如果

$_POST[firstname] =mypicture.php%00

并且

$extension=.jpg;

这段代码存在安全漏洞,其结果为

test.php%00.jpg //test.php uploaded on server.

欲了解更多信息,请查看此链接:

https://www.owasp.org/index.php/Unrestricted_File_Upload

这个链接介绍了有关不受限制的文件上传的信息。

2
首先,找到扩展名:
$pos = strrpos($filename, '.');
if ($pos === false) 
{
    // file has no extension; do something special?
    $ext = "";
}
else
{
    // includes the period in the extension; do $pos + 1 if you don't want it
    $ext = substr($filename, $pos);
}

那么请随意命名您的文件,并在名称后添加扩展名:
$newFilename = "foobar" . $ext;
move_uploaded_file($_FILES['picture']['tmp_name'], 'peopleimages/' . $newFilename);

编辑:仔细想想,这些都不是最优的解决方案。文件扩展名通常描述文件类型,但并非总是如此。例如,您可以将 .png 文件重命名为 .jpg 扩展名,大多数应用程序仍然会检测到它是一个 png 文件。除此之外,某些操作系统根本不使用文件扩展名来确定文件类型。
使用 $_FILE 上传,您还会得到一个 type 元素,表示您收到的文件的 MIME 类型。如果可以的话,我建议您依靠它而不是给定的扩展名:
$imagetypes = array(
    'image/png' => '.png',
    'image/gif' => '.gif',
    'image/jpeg' => '.jpg',
    'image/bmp' => '.bmp');
$ext = $imagetypes[$_FILES['myfile']['type']];

你可以在这里获取更完整的MIME类型列表

0
move_uploaded_file($_FILES["picture"]["tmp_name"], "peopleimages/" . "$_POST[lastname]" . '_' . "$_POST[firstname]." . pathinfo($_FILES["picture"]["tmp_name"], PATHINFO_EXTENSION));

1
那是一行很长的代码,大多数编码标准都建议避免这样做,因为可读性差。我建议你遵循它们。 - Niels Bom

0

你可以随时:

$original = explode('.', $_FILES["picture"]["tmp_name"]);
$extension = array_pop($original);

move_uploaded_file($_FILES["picture"]["tmp_name"], "peopleimages/" . "$_POST[lastname]" . '_' . "$_POST[firstname]". $extension);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接