Gemini API 不支持直接上传文件,PHP 必须先将 $_FILES 转为 Base64(仅限图像,≤20MB)或上传至公网可访问 URL;Base64 方式需构造含 inlineData 的 JSON 并设 Content-Type: application/json;URL 方式需确保 fileUri 可被 Google 直连且无 query 参数;API 密钥严禁硬编码,须通过环境变量或 .env 管理。

PHP 上传文件到 Gemini API 需要自己处理,Gemini 不支持直接文件上传
Google Gemini API(包括 generativeai SDK)本身不提供文件上传端点——它只接受已存在的、可公开访问的文件 URL,或 Base64 编码的图片内容(仅限部分模型如 gemini-1.5-flash 和 gemini-1.5-pro)。PHP 后端不能把用户上传的 $_FILES 直接 POST 给 Gemini,必须先完成中转。
常见错误现象:400 Bad Request 带 "content must be a valid URI or base64 data";或 404 因传了本地路径如 /tmp/phpabc123。
- 必须将
$_FILES['file']['tmp_name']读取后,转换为 Base64(仅限图像)或上传至公网可访问存储(如 Cloud Storage、S3、甚至你自己的带 HTTPS 的临时目录) - 若用 Base64:仅支持
image/*类型,且总长建议 ≤ 20MB;需拼接前缀如"data:image/png;base64," - 若走 URL 路径:确保该 URL 可被 Google 服务直连(无 IP 黑名单、无登录跳转、无 Referer 限制),且响应头含
Content-Type
用 cURL 发送含 Base64 图片的 multipart 请求给 gemini-1.5-flash
这是最轻量的集成方式,适合小图(头像、截图、票据照片),绕过对象存储配置。关键在构造符合 Gemini 要求的 JSON payload 和正确设置 Content-Type。
容易踩的坑:curl_setopt($ch, CURLOPT_POSTFIELDS, $json) 会自动设为 application/x-www-form-urlencoded,但 Gemini 要求 application/json;同时 Base64 字符串不能换行、不能含空格。
立即学习“PHP免费学习笔记(深入)”;
- 用
file_get_contents()读取$_FILES['image']['tmp_name'],再用base64_encode()编码 - 构建 payload 时,
parts数组里写["inlineData" => ["mimeType" => "image/jpeg", "data" => $base64]],不是fileData或uri - cURL 必须显式设置:
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']) - API 地址格式为:
https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=YOUR_API_KEY
$base64 = base64_encode(file_get_contents($_FILES['image']['tmp_name']));
$payload = json_encode([
'contents' => [[
'parts' => [[
'inlineData' => [
'mimeType' => $_FILES['image']['type'],
'data' => $base64
]
]]
]],
'generationConfig' => ['temperature' => 0.2]
]);
上传文件到临时 HTTPS 可访问路径再喂给 Gemini(通用方案)
当文件类型不限于图片(PDF、DOCX)、或体积较大(>4MB)、或需复用时,必须走“上传 → 存储 → 提供公网 URL”流程。PHP 本身不提供托管能力,得借助外部服务或简易静态托管。
性能影响:多一次 I/O + 网络上传延迟;兼容性影响:若用自建目录,务必确认 Web 服务器(Nginx/Apache)已启用 MIME 类型推断,否则 Gemini 返回 "invalid mime type"。
- 推荐做法:生成唯一子目录(如
uploads/20240520/abc123.pdf),用move_uploaded_file()存入 Webroot 下可公开访问的位置 - 确保该路径可通过 HTTPS 访问(如
https://yoursite.com/uploads/20240520/abc123.pdf),且 Nginx 配置未禁用非 HTML 类型(检查location ~ \.pdf$是否有add_header Content-Type application/pdf) - 请求 Gemini 时,
parts改用["fileData" => ["fileUri" => $public_url, "mimeType" => $_FILES['file']['type']]] - 注意:Gemini 不支持
fileUri指向 localhost、127.0.0.1 或私有内网地址,也不支持带 query 参数的 URL(如?t=123)
API 密钥和权限必须严格隔离,别硬编码在 PHP 文件里
很多人把 GEMINI_API_KEY 写死在 index.php 里,导致 Git 泄露或被直接 curl 获取。这不是功能问题,而是上线即崩溃的风险点。
真实场景下,Web 服务器(PHP-FPM)与前端分离部署时,API 密钥绝不能经浏览器或 JS 触发;所有 Gemini 请求必须由 PHP 后端发起并代理。
- 把密钥存在环境变量(
putenv('GEMINI_API_KEY=xxx'))或.env(配合vlucas/phpdotenv),并在php.ini中禁用display_errors - 不要在 JavaScript 里调用 Gemini API;前端只传文件给 PHP 接口,由 PHP 完成调用并返回结构化结果
- 使用
escapeshellarg()包裹任何拼接到 shell 命令中的用户输入(比如调用gsutil上传时),避免命令注入
Base64 方式看着简单,但图像尺寸、编码完整性、JSON 转义稍有偏差就静默失败;URL 方式依赖基础设施,但更可控、可审计。选哪种,取决于你有没有现成的 HTTPS 文件托管能力。



















