PHP检查文件是否存在
PHP检查文件是否存在
引言
上传头像、读取配置、缓存命中判断之前,都要先确认文件是否存在。PHP里file_exists判断文件或目录,is_file专门判断普通文件,is_dir判断目录,三者语义不同,用错会把目录当成文件导致后续读取报错。
file_exists 判断存在
$path = './config/config.php';
if (file_exists($path)) {
echo '文件存在';
} else {
echo '文件不存在';
}
文件或目录存在都返回true,路径不存在、权限不可访问返回false。
is_file 判断是普通文件
if (is_file($path)) {
echo '这是一个普通文件';
}
目录、符号链接、管道都返回false,读取文件前用它最稳妥。
is_dir 判断目录
$dir = './uploads';
if (is_dir($dir)) {
echo '目录存在';
}
专门判断目录,适合上传前检查目录是否已建。
判断可读性再操作
if (is_file($path) && is_readable($path)) {
$content = file_get_contents($path);
}
存在不代表可读,权限不足时file_get_contents会警告,先加is_readable判断。
路径拼接注意
$file = __DIR__ . '/../data/' . $name;
用绝对路径拼接,避免相对路径受当前工作目录影响,跨目录包含时不容易找错文件。
注意事项
- file_exists缓存了文件状态,删改文件后可用clearstatcache清缓存;
- 判断普通文件用is_file,别只靠file_exists,目录会误判;
- 检查存在后还要is_readable/is_writable,权限是另一道关;
- 文件名含中文或特殊字符注意编码统一,避免误判不存在;
- 防路径穿越,用户传入的文件名先过滤..和绝对路径;
- 大量循环判断文件时注意stat缓存带来的性能影响。
总结
file_exists判断文件或目录是否存在,is_file判断普通文件,is_dir判断目录,is_readable/is_writable判断读写权限。读取配置、上传文件、缓存命中前先做存在性和权限判断。注意clearstatcache清理状态缓存,用户传入文件名要防路径穿越,跨目录用DIR拼绝对路径,避免相对路径偏移导致找错文件。
PHP获取文件扩展名
PHP获取文件扩展名
引言
文件上传、附件处理、图片裁剪时都要先拿到后缀判断类型。别用explode切字符串硬切,pathinfo是PHP专门解析路径的函数,能干净返回扩展名、文件名、目录名各部分。
pathinfo 标准用法
$file = '/var/www/upload/photo.2024.jpg';
$info = pathinfo($file);
echo $info['extension']; // jpg
echo $info['filename']; // photo.2024
echo $info['dirname']; // /var/www/upload
一次返回路径各组成部分,最稳妥。
只取扩展名
$ext = pathinfo($file, PATHINFO_EXTENSION);
// jpg
传第二个常量直接拿扩展名,省一次数组取值。
处理无扩展名文件
$ext = pathinfo('README', PATHINFO_EXTENSION);
// 空字符串,不会报错
没扩展名时返回空串,记得做空判断。
大写转小写统一
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
用户传JPG、Jpg、jpg都归一,上传校验用统一小写比较。
不要用explode硬切
// 反面例子:photo.2024.jpg 会切错
$parts = explode('.', $file);
$ext = end($parts);
多级点号文件名会取错,pathinfo按最后一个点正确取后缀。
注意事项
- 扩展名不等于真实MIME类型,校验文件内容要用finfo;
- 扩展名可伪造,上传安全不能只信后缀;
- PATHINFO_EXTENSION对".htaccess"这种点开头文件返回空;
- 中文文件名不受影响,pathinfo按字节正确处理;
- 取到扩展名后trim并strtolower再做白名单校验;
- 别把扩展名当安全依据,配合大小限制和重命名存储。
总结
pathinfo($file, PATHINFO_EXTENSION)取扩展名最稳,filename拿文件名、dirname拿目录,无扩展名返回空串记得判断,业务里统一strtolower小写。不要用explode切多级点号文件名。扩展名只是展示用,真实类型靠finfo判断,上传安全还需白名单加文件内容校验和重命名存储。
PHP文件上传校验
PHP文件上传校验
引言
文件上传是网站高频功能,也是最容易出安全问题的地方。只判断后缀名,黑客可以把木马改名为图片绕过,上传到服务器执行。上传必须做多层校验。
必须校验的内容
- 检查上传错误码,确认文件确实上传成功;
- 限制文件大小,防止超大文件占满磁盘;
- 白名单校验扩展名,只允许jpg/png等指定类型;
- 读取文件真实MIME类型,不能只信前端传的type;
- 重新生成随机文件名,避免原文件名覆盖或路径穿越;
- 上传目录禁止执行PHP脚本。
基础校验示例
<?php
$allow = ['jpg','png','gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION));
if(!in_array($ext,$allow)){
exit('类型不允许');
}
if($_FILES['file']['size'] > 2*1024*1024){
exit('文件过大');
}
//获取真实类型
$info = getimagesize($_FILES['file']['tmp_name']);
if(!$info) exit('不是合法图片');
//随机重命名
$newName = uniqid().'.'.$ext;
move_uploaded_file($_FILES['file']['tmp_name'],'./upload/'.$newName);
服务端加固
- Nginx/Apache配置上传目录禁止解析php;
- 图片上传后重新压缩生成,破坏木马脚本;
- 关闭上传目录的执行权限;
- 定期扫描上传目录文件。
总结
文件上传安全核心:不信任前端、白名单、校验真实类型、随机改名、目录隔离。多层校验才能防止webshell上传,保护服务器安全。
Linux上传下载文件,rz和sz命令使用
前言
经常需要从本地电脑上传文件到服务器,或者把服务器上的文件下载到本地。除了用 FTP 工具,还有更简单的 rz 和 sz 命令,直接在终端里就能操作。本文讲一下怎么用。
安装 lrzsz
rz 和 sz 命令来自 lrzsz 包,CentOS 最小化安装可能没有:
yum install -y lrzsz
Ubuntu 的话:
apt install -y lrzsz
rz 上传文件(从本地上传到服务器)
基本用法
直接输入:
rz
执行后会弹出一个文件选择窗口,选你要上传的文件,点确定就开始上传了。
注意: 文件会上传到你当前所在的目录。
指定文件名
上传后直接改成指定名字:
rz -y 新文件名
-y 是覆盖同名文件。
上传多个文件
执行 rz 之后在文件选择窗口可以按住 Ctrl 多选。
sz 下载文件(从服务器下载到本地)
下载单个文件
sz 文件名
比如下载 index.html:
sz index.html
执行后会弹出保存窗口,选保存位置就开始下载了。
下载多个文件
sz 文件1 文件2 文件3
比如:
sz a.txt b.txt c.txt
下载整个目录(先打包)
sz 不能直接下载目录,要先打包:
tar -zcvf backup.tar.gz /var/www/html
sz backup.tar.gz
常见使用场景
场景1:上传配置文件
# 先进入要上传的目录
cd /etc/nginx/conf.d/
# 上传
rz
选本地的 nginx 配置文件,上传完就直接放到这个目录了。
场景2:下载日志文件
# 进入日志目录
cd /var/log/nginx/
# 下载访问日志
sz access.log
场景3:上传压缩包
本地把项目打包成 zip,然后:
cd /var/www/html/
rz
选本地的项目 zip 文件,上传完再解压。
常见坑
坑1:rz 命令找不到
执行 rz 提示 command not found。
原因: 没装 lrzsz 包。
解决:
yum install -y lrzsz
坑2:上传的文件不知道去哪了
执行了 rz,但不知道文件上传到哪了。
原因: 文件上传到你当前所在的目录。
解决: 上传前先 pwd 看一下当前目录在哪。
坑3:用了某些 SSH 工具不支持 rz/sz
有些 SSH 客户端(比如 Windows 自带的 cmd)不支持 rz/sz。
原因: rz/sz 需要终端支持 ZModem 协议。
解决: 用支持的 SSH 工具,比如 Xshell、SecureCRT、FinalShell、MobaXterm。
坑4:大文件上传慢
上传几百 M 的文件特别慢。
原因: rz/sz 走的是 SSH 通道,速度不快。
解决: 大文件用 SFTP 或者专门的传输工具(FileZilla)更快。
坑5:上传的文件是乱码
上传完中文文件名变成乱码。
原因: 编码问题。
解决: 用英文文件名,或者先打包成 zip 再上传。
总结
| 命令 | 作用 |
|---|---|
rz |
从本地上传文件到服务器 |
sz 文件名 |
从服务器下载文件到本地 |
前提: 要先装 lrzsz 包,而且 SSH 工具要支持 ZModem 协议。
小文件用 rz/sz 很方便,大文件还是用 SFTP 吧。
遇到问题加QQ23979811 协助处理