You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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);
错误原因分析
  1. 第一种写法逻辑混乱:

    • 既尝试解析php://input的JSON(但multipart数据并非JSON格式),又操作$_FILES,完全冗余
    • 对$_FILES["file"]["tmp_name"]的内容做base64解码是错误操作——multipart上传的临时文件是原始二进制图片,并非base64字符串,解码后会直接破坏文件结构,导致格式错误或0字节无效文件
    • 重复定义$file_ext,逻辑冗余且易引发冲突
  2. 第二种写法关键缺失:

    • 核心变量$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:06:13