如何在PHP中使用file_get_contents上传图片?解决格式错误问题
问题描述
我是React.js/Next.js新手,前端通过multipart form data发送图片数据,PHP端处理上传时,要么提示“我们不支持此格式”,要么生成0字节的无效图片。试过两种写法都失败,求用file_get_contents实现图片上传的正确方式。
我的两种错误写法:
第一种写法
$data = json_decode(file_get_contents("php://input"), TRUE); $files=file_get_contents($_FILES["file"]["tmp_name"]); $image = base64_decode(explode( ',', $files)[1]); $file_name =$_FILES['file']['name']; $file_ext = strtolower( end(explode('.',$file_name))); define('UPLOAD_DIR', 'uploads/'); $file_ext = pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION); $file_name = UPLOAD_DIR . uniqid() . time() . '.' . $file_ext; move_uploaded_file($_FILES["file"]["tmp_name"], $file_name);
第二种写法
$file_name =$_FILES['file']['name']; $file_ext = strtolower( end(explode('.',$file_name))); define('UPLOAD_DIR', 'uploads/'); $image_parts = explode(";base64,", $image); $image_type_aux = explode("image/", $image_parts[0]); $image_type = $image_type_aux[1]; $image_base64 = base64_decode($image_parts[1]); $file = UPLOAD_DIR . uniqid() . '.'.$file_ext; file_put_contents($file, $image_base64);
错误原因分析
第一种写法逻辑混乱:
- 既尝试解析
php://input的JSON(但multipart数据并非JSON格式),又操作$_FILES,完全冗余 - 对
$_FILES["file"]["tmp_name"]的内容做base64解码是错误操作——multipart上传的临时文件是原始二进制图片,并非base64字符串,解码后会直接破坏文件结构,导致格式错误或0字节无效文件 - 重复定义
$file_ext,逻辑冗余且易引发冲突
- 既尝试解析
第二种写法关键缺失:
- 核心变量
$image未定义,直接调用explode会触发报错,根本无法执行到文件保存步骤 - 完全未对接
$_FILES的上传数据,等于操作空内容,自然生成0字节文件
- 核心变量
正确的
file_get_contents上传实现 // 定义上传目录,确保目录存在且具备写入权限 define('UPLOAD_DIR', 'uploads/'); if (!is_dir(UPLOAD_DIR)) { mkdir(UPLOAD_DIR, 0755, true); } // 校验请求方式与上传参数 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) { $uploadedFile = $_FILES['file']; // 检查上传过程是否出现错误 if ($uploadedFile['error'] !== UPLOAD_ERR_OK) { die("上传错误:错误码" . $uploadedFile['error']); } // 读取临时文件的二进制内容 $imageContent = file_get_contents($uploadedFile['tmp_name']); if (!$imageContent) { die("无法读取上传文件内容"); } // 验证文件真实类型(避免伪造后缀的恶意文件) $finfo = new Finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->buffer($imageContent); $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; if (!in_array($mimeType, $allowedTypes)) { die("不支持此文件格式"); } // 根据MIME类型匹配正确的文件后缀 $extMap = [ 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/webp' => 'webp' ]; $fileExt = $extMap[$mimeType]; // 生成唯一文件名,避免文件覆盖 $fileName = UPLOAD_DIR . uniqid() . '.' . $fileExt; // 使用file_put_contents保存文件 if (file_put_contents($fileName, $imageContent)) { echo "上传成功,文件路径:" . $fileName; } else { die("保存文件失败,请检查uploads目录的写入权限"); } } else { die("无效的请求"); }
前端注意事项(React/Next.js)
确保正确构建FormData发送请求,不要手动将图片转为base64:
// 示例:处理文件选择并发送上传请求 const handleFileUpload = (e) => { const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append('file', file); fetch('/upload.php', { method: 'POST', body: formData // 无需手动设置Content-Type,浏览器会自动添加正确的multipart/form-data请求头 }) .then(res => res.text()) .then(data => console.log(data)) .catch(err => console.error(err)); };
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

