0

0

如何安全重命名上传的图片文件(去除空格与特殊字符)

心靈之曲

心靈之曲

发布时间:2026-01-15 11:53:20

|

675人浏览过

|

来源于php中文网

原创

如何安全重命名上传的图片文件(去除空格与特殊字符)

本文介绍如何在php文件上传过程中,使用自定义清洗函数自动清理原始文件名中的空格、符号和重复连字符,生成符合web规范的安全文件名,并确保数据库记录与实际存储路径一致。

在处理用户上传的图片时,原始文件名常包含空格(如 "my photo.jpg")、特殊字符(如 "credit@#%card.png")或连续标点(如 "file----2024.jpg"),这些不仅影响URL可读性与SEO,还可能引发服务器解析异常、安全风险(如路径遍历尝试)或CDN/缓存兼容性问题。PHP无法在客户端修改真实文件名(浏览器出于安全限制禁止JS重命名本地文件),但完全可以在服务端接收后、保存前,对文件名进行标准化清洗——这正是最佳实践所在。

以下是一个健壮、可复用的解决方案,整合了您提供的 cleanStr() 函数,并优化了上传逻辑:

✅ 推荐实现代码(含关键改进)

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['id'], $_FILES['files']['name'])) {
    // 清洗函数:统一空格为短横线,移除非字母数字及短横线字符,压缩多连横为单横
    function cleanStr($string) {
        $string = str_replace(' ', '-', $string);
        $string = preg_replace('/[^A-Za-z0-9\-]/', '', $string);
        return preg_replace('/-+/', '-', trim($string, '-'));
    }

    $count = 0;
    $sql = "INSERT INTO images (post_id, name, image) VALUES (?, ?, ?)";
    $stmt = $db->prepare($sql);

    // 定义存储路径(建议使用绝对路径提升可靠性)
    $uploadDir = __DIR__ . '/uploads/documents/';
    $webPath = './uploads/documents/'; // 相对路径,用于前端展示或数据库存储

    $allowedExts = ['png', 'jpg', 'jpeg'];

    foreach ($_FILES['files']['name'] as $index => $originalName) {
        $tmpPath = $_FILES['files']['tmp_name'][$index];
        $error   = $_FILES['files']['error'][$index];

        // 跳过空文件或上传错误
        if (empty($tmpPath) || $error !== UPLOAD_ERR_OK) continue;

        // 解析原始文件信息
        $ext  = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        $base = pathinfo($originalName, PATHINFO_FILENAME);

        // 基础校验:扩展名 + 是否为有效图像
        if (!in_array($ext, $allowedExts) || !getimagesize($tmpPath)) continue;

        // ✅ 关键步骤:清洗文件名并生成唯一新名
        $safeName = cleanStr($base) ?: 'unnamed'; // 防止清洗后为空
        $timestamp = date('Y-m-d-his');
        $finalName = "{$timestamp}-{$safeName}.{$ext}";
        $savePath  = $uploadDir . $finalName;
        $dbPath    = $webPath . $finalName;

        // 执行移动与入库
        if (move_uploaded_file($tmpPath, $savePath)) {
            $stmt->execute([$_GET['id'], $finalName, $dbPath]);
            $count++;
        }
    }

    // 重定向并携带统计信息
    $redirect = "result.php?id={$_GET['id']}&action=UPLOADED&total={$count}";
    exit(header("Location: {$redirect}"));
}

⚠️ 注意事项与增强建议

  • cleanStr() 补充说明
    原函数未处理首尾连字符,可能导致 "-abc-" → "abc-"。上述代码中 trim($string, '-') 已修复此问题,确保生成的文件名不以 - 开头或结尾。

  • 安全性强化

    Video Ocean
    Video Ocean

    人人皆导演,让视频创作变得轻松自如

    下载
    • 使用 getimagesize() 替代仅靠扩展名判断,防止伪造 .jpg 后缀的恶意脚本;
    • move_uploaded_file() 是必须使用的函数,它能阻止临时文件被篡改或重放攻击;
    • 避免直接拼接 $_FILES['files']['name'] 到路径中,始终清洗后再组合。
  • 可扩展性提示

    • 如需支持中文,可将 cleanStr() 中正则替换为 preg_replace('/[^\p{Han}\p{L}\p{N}\-]/u', '', $string)(启用 Unicode 模式);
    • 生产环境建议添加文件大小限制($_FILES['files']['size'][$i])、防重名机制(如 uniqid() 或哈希前缀);
    • 数据库存储推荐保存相对路径(如 ./uploads/...),而非绝对路径,便于迁移部署。

通过以上方式,您不仅能彻底解决“credi-- @% sdfdsf..####tcard.jpg”这类混乱文件名问题,还能构建更安全、可维护的上传流程。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

576

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

6175

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

492

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

Js中concat和push的区别
Js中concat和push的区别

Js中concat和push的区别:1、concat用于将两个或多个数组合并成一个新数组,并返回这个新数组,而push用于向数组的末尾添加一个或多个元素,并返回修改后的数组的新长度;2、concat不会修改原始数组,是创建新的数组,而push会修改原数组,将新元素添加到原数组的末尾等等。本专题为大家提供concat和push相关的文章、下载、课程内容,供大家免费下载体验。

240

2023.09.14

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.3万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号