如何在PHP上传程序中重命名指定类型的文件扩展名?
问题原因排查
- 当检测到文件后缀为
sh时,你仅更新了$newFileName变量为.txt后缀,没有同步更新保存文件用的$fileUploadPath变量。$fileUploadPath还是用最开始生成的带.sh后缀的路径值,所以move_uploaded_file实际把文件存成了随机名.sh,你跳转的地址是随机名.txt,自然找不到对应文件,看起来就像没有上传成功。 - 执行
header()跳转后没有添加exit()/die()终止代码执行,可能导致后续逻辑异常。 - 目前代码仅处理了后缀属于
$notAllowed的文件,其余后缀的文件没有任何上传逻辑,也没有错误提示。 - 路径拼接需要注意
/uploads/的开头斜杠是否和getcwd()返回的路径匹配,避免出现路径拼接错误。
修复方案
下面是修复后的完整代码:
$fileName = $_FILES["file"]["name"]; $fileSize = $_FILES["file"]["size"]; $fileExt = explode(".", $fileName); $fileRealExt = strtolower(end($fileExt)); $uploadDirectory = "/uploads/"; $currentDirectory = getcwd(); $fileTmpName = $_FILES["file"]["tmp_name"]; $notAllowed = array("sh"); if (isset($_POST["submit"])) { // 先判断上传是否有系统级错误 if ($_FILES["file"]["error"] !== UPLOAD_ERR_OK) { header("Location: error.php"); exit(); } // 统一生成最终文件名 if (in_array($fileRealExt, $notAllowed)) { $newFileName = uniqid("", true) . ".txt"; } else { $newFileName = uniqid("", true) . "." . $fileRealExt; } // 统一生成上传路径,避免变量不同步 $fileUploadPath = $currentDirectory . $uploadDirectory . $newFileName; // 提前检查上传目录是否存在、是否有写入权限 if (!is_dir($currentDirectory . $uploadDirectory) || !is_writable($currentDirectory . $uploadDirectory)) { header("Location: error.php"); exit(); } $didUpload = move_uploaded_file($fileTmpName, $fileUploadPath); if ($didUpload) { header("Location: $uploadDirectory$newFileName"); exit(); } else{ header("Location: error.php"); exit(); } } ?>
额外优化建议
- 可以在修改sh后缀为txt的同时,对文件内容做安全校验,避免恶意代码伪装成其他格式上传。
- 可以限制上传文件的大小,避免服务器存储被占满。
- 原代码中
$fileName = $fileExt[0] . ".txt";没有实际使用,可以删除,或者如果需要保留原文件名前缀,可以把uniqid和原文件名结合使用。
内容的提问来源于stack exchange,提问作者Funnydog204
相关产品推荐
相关产品推荐

