拖拽上传本质是前端交互,PHP仅接收文件;前端用drop事件捕获文件并借FormData通过fetch发送,PHP端须校验$_FILES'file'为0、is_uploaded_file()为true,并配置file_uploads=On等参数。

拖拽上传本质是前端交互,PHP只负责接收文件
PHP 本身不处理拖拽逻辑,它只是接收前端通过 POST(或更常见的是 FormData)提交的文件。关键在于前端用 drop 事件捕获文件,再用 fetch 或 XMLHttpRequest 发送到 PHP 接口。如果你发现“PHP 拖拽没反应”,大概率是前端没发、或后端没正确读取 $_FILES。
PHP 端必须检查 $_FILES 和临时文件状态
拖拽上传和普通表单上传走的是同一套 PHP 文件上传机制,所以必须依赖 $_FILES 超全局数组。但容易忽略几个致命点:
-
$_FILES['file']['error']必须为0(UPLOAD_ERR_OK),否则说明上传失败(比如UPLOAD_ERR_INI_SIZE表示超出upload_max_filesize) -
$_FILES['file']['tmp_name']必须是非空字符串且is_uploaded_file()返回true——直接move_uploaded_file()前不校验,可能被伪造路径攻击 - PHP 配置项
file_uploads = On、post_max_size和upload_max_filesize必须足够大,且单位一致(如都用M)
前端发送时要用 FormData,不能直接 JSON.stringify
拖拽拿到的 File 对象不能 JSON 序列化,必须塞进 FormData。否则 PHP 的 $_FILES 为空,$_POST 里也收不到二进制数据。
const dropArea = document.getElementById('drop');
dropArea.addEventListener('drop', async (e) => {
e.preventDefault();
const files = e.dataTransfer.files;
const formData = new FormData();
for (let file of files) {
formData.append('file', file); // 注意 key 名要和 PHP 中 $_FILES['file'] 一致
}
await fetch('upload.php', { method: 'POST', body: formData });
});
简单安全的 PHP 接收示例(支持单/多文件)
不要直接信任 $_FILES['file']['name'] 做保存名,尤其防 ../ 路径遍历;扩展名也要白名单校验,不能只看 pathinfo($name, PATHINFO_EXTENSION)。
立即学习“PHP免费学习笔记(深入)”;
<?php
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
foreach ($_FILES['file']['error'] as $index => $error) {
if ($error !== UPLOAD_ERR_OK) continue;
$tmpName = $_FILES['file']['tmp_name'][$index];
if (!is_uploaded_file($tmpName)) continue;
$originalName = $_FILES['file']['name'][$index];
$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
if (!in_array($ext, ['jpg', 'png', 'pdf', 'txt'])) continue;
$safeName = uniqid() . '.' . $ext;
$targetPath = $uploadDir . $safeName;
if (move_uploaded_file($tmpName, $targetPath)) {
echo json_encode(['success' => true, 'file' => $safeName]);
}
}
?>
多文件上传时 $_FILES 是二维数组,这点和表单 name="file[]" 一致;如果前端只传一个文件,$_FILES['file'] 是一维,代码需适配——实际项目建议统一按多文件逻辑处理。
最常被跳过的一步:没给 uploads/ 目录写权限,或者 SELinux / open_basedir 限制了写入路径。出错时先 var_dump($_FILES) 和 error_log(getcwd()) 看清真实环境状态。



















