您的当前位置:首页 > 探索 > 网站上传文件 正文

网站上传文件

时间:2026-10-17 04:37:05 来源:网络整理 编辑:探索

核心提示

服务器日志里,那条500错误像根刺一样扎眼。用户上传的是一张2.4MB的JPEG,不算大,却让PHP进程直接崩溃。查了半天,问题出在图片的EXIF信息里藏了一段畸形数据——不是攻击,纯粹是某台老相机写

服务器日志里,网站文件那条500错误像根刺一样扎眼。上传用户上传的网站文件是一张2.4MB的JPEG,不算大,上传却让PHP进程直接崩溃。网站文件查了半天,上传问题出在图片的网站文件EXIF信息里藏了一段畸形数据——不是攻击,纯粹是上传某台老相机写坏了元数据。这种事儿,网站文件代码审查根本发现不了。上传

文件上传从来不是网站文件“把文件挪个地方”那么简单。你面对的上传是用户手里五花八门的设备、操作系统、网站文件浏览器,上传还有他们随手改过的网站文件文件后缀名。有人把PDF改成PNG传上来,有人上传一个0字节的空文件,还有人用中文文件名,里面混着全角括号和emoji。这些不是边缘情况,是每天都会发生的常态。

我见过最离谱的一次,是某用户上传了一个名为“简历(最终版)(1).docx”的文件,实际内容是个zip压缩包。系统按docx处理,安全扫描直接跳过,结果解压出来是个带宏的Office文档。幸亏沙箱环境拦住了,不然整个内网都得遭殃。从那以后,我的上传接口强制校验文件头(magic bytes),后缀名只是参考。

真正的坑在存储层。你把文件存本地磁盘,服务器一扩容就麻烦;存云存储,又得考虑跨区域同步的延迟。更别提那些需要生成缩略图的场景——一张RAW格式的照片可能50MB,你得在内存里处理,稍不留神就OOM。我有个同事图省事,直接用file_get_contents()读取整个上传文件,结果用户传了个4GB的视频,直接把8GB内存的服务器干宕机了。后来改成流式读取,分块处理,才消停。

还有个细节容易被忽略:文件名里的路径穿越。用户传个../../etc/passwd,如果你直接把文件名拼进存储路径,等于白送攻击者一个写文件漏洞。正确做法是重命名文件,用随机字符串或者日期哈希,存数据库里做映射。丑是丑了点,但安全。

上传进度条是另一个玄学。你以为用XMLHttpRequest就能搞定的进度显示,实际上得处理分片上传、断点续传、甚至用户中途切网的情况。我见过一个项目,前端用FormData直接post整个文件,连个loading状态都没有,大文件传一半浏览器直接超时,用户还以为是网站坏了。后来换成用fetch配合ReadableStream做流式上传,才勉强能看。

最后,别忘了校验文件类型和大小。不是所有用户都懂“图片别超过5MB”,但你的服务器得替他们兜底。我现在的做法是:前端先压缩,后端再严格校验,双重保险。即便如此,每周还是能抓到几个绕过前端限制传大文件的——他们用curl,或者干脆改前端代码。别指望用户按你的规则来,你只能把自己的防线加固。

上传功能写多了,你会形成一种条件反射:看到multipart/form-data就下意识检查Content-Type,看到move_uploaded_file()就想起权限设置。这活儿不性感,但每个细节都可能是事故现场。反正我现在的原则很简单:能不用原文件名就不用,能限制大小就限制,能白名单扩展名就白名单。剩下的,就交给日志和监控去盯吧。