如何在 JSON 请求体中嵌入文件数据并被 PHP REST 接口正确接收

14次阅读

如何在 JSON 请求体中嵌入文件数据并被 PHP REST 接口正确接收

json 请求体无法直接携带二进制文件,需将文件转为 base64 编码字符串嵌入对象字段;后端 php 需主动解码还原,而非依赖 $_files(该变量仅适用于 multipart/form-data 请求)。

在构建 REST API 时,一个常见误区是试图在 application/json 类型的 raw 请求体中直接“放入”文件(如通过 “upload_file”: ),这是技术上不可行的jsON 规范仅支持字符串、数字、布尔值、NULL、数组和对象,不支持原始二进制数据。因此,若你坚持使用 Content-Type: application/json 并在请求体中以结构化 JSON 发送文件,唯一合规且通用的做法是将文件内容编码Base64 字符串

例如,你的请求体应改为如下格式:

{   "id": 1,   "mydata": [     {       "entity_id": 1,       "upload_file": "UEsDBBQAAAaiAJiR..." // Base64 编码后的文件内容(如 PNG、pdf 等)     },     {       "entity_id": 2,       "upload_file": "iVBORw0KGgoAAAANSUhEUg..."     }   ] }

⚠️ 注意:

  • Base64 编码会使数据体积膨胀约 33%,不适合大文件(建议单文件 ≤ 5 MB);
  • 必须在 JSON 中明确约定字段语义(如 upload_file 表示 Base64 编码的原始文件内容,非文件名或路径);
  • 前端需确保正确读取文件并编码(如 javaScript 使用 FileReader.readAsDataURL() 后截取 base64 部分),后端需严格校验和解码。

php 后端接收与处理示例:

立即学习PHP免费学习笔记(深入)”;

// 1. 获取原始 JSON 输入 $jsonInput = file_get_contents('php://input'); $data = json_decode($jsonInput, true);  if (json_last_error() !== JSON_ERROR_NONE) {     http_response_code(400);     echo json_encode(['error' => 'Invalid JSON']);     exit; }  // 2. 遍历 mydata 数组,解码并保存每个 upload_file foreach ($data['mydata'] as $item) {     $entityId = $item['entity_id'] ?? null;     $base64Data = $item['upload_file'] ?? '';      if (empty($base64Data)) {         continue; // 跳过空文件     }      // 验证 Base64 格式(简化版)     if (!preg_match('/^data:(.*?);base64,(.*)$/i', $base64Data, $matches)) {         // 若无 data URL 前缀,直接尝试解码(假设纯 base64 字符串)         $binary = base64_decode($base64Data);     } else {         $binary = base64_decode($matches[2]);     }      if ($binary === false) {         throw new InvalidArgumentException("Invalid Base64 string for entity_id: $entityId");     }      // 3. 可选:推断 MIME 类型(如需)     $finfo = finfo_open(FILEINFO_MIME_TYPE);     $mimeType = finfo_buffer($finfo, $binary);     finfo_close($finfo);      // 4. 保存文件(示例:按 entity_id 命名)     $filename = "/uploads/entity_{$entityId}_" . date('YmdHis') . '.bin';     file_put_contents($filename, $binary);      // ✅ 此时 $binary 即为原始文件字节流,可进一步校验、转存、解析等 }

? 关键总结:

  • $_FILES 全局变量仅在 multipart/form-data 请求中自动填充,对 JSON 请求完全不可用;
  • 若需保留 $_FILES 的便利性(如自动临时文件、大小限制、错误码等),应改用 form-data 模式,并将 mydata 数组序列化为字段名(如 mydata[0][entity_id] + mydata[0][upload_file]),但需服务端做特殊解析;
  • Base64 方案简洁、跨平台兼容性强,是 JSON-first 架构下的标准实践,但务必配套实现完整性校验(如添加 upload_file_hash 或 upload_file_size 字段辅助验证)。

选择方案前,请根据实际场景权衡:小文件、强结构化需求 → 用 Base64 + JSON;大文件、上传进度/断点续传需求 → 回归 multipart/form-data + 自定义字段解析。

text=ZqhQzanResources