Gemini File API 是一个完全独立的模块,与其他 API 逻辑完全隔离,不会相互干扰。
支持的功能:
注意:本模块仅实现了文件上传和列表功能,这是使用 Gemini File API 的核心功能。如需获取单个文件信息或删除文件,可以通过列表接口获取所有文件信息。
router/gemini_file_router.goGET /v1beta/files - 列出文件POST /upload/v1beta/files - 上传文件middleware/gemini_file_auth.gocontroller/relay_gemini_file.goRelayGeminiFileList - 列出文件RelayGeminiFileUpload - 上传文件relay/channel/gemini/file_helper.go本模块支持两种上传方式:
适合小文件(< 100MB),一次性上传。
curl -X POST "http://your-api.com/upload/v1beta/files?key=YOUR_API_KEY" \
-F "file=@/path/to/file.pdf" \
-F "display_name=My Document"
注意:此方式可能无法正确设置 MIME 类型,文件会被标记为 application/octet-stream。
适合大文件或需要正确 MIME 类型的场景。分为两步:
步骤 1:初始化上传会话
# 自动获取文件信息
VIDEO_PATH="/path/to/video.mp4"
MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}")
NUM_BYTES=$(wc -c < "${VIDEO_PATH}")
# 初始化上传
curl "http://your-api.com/upload/v1beta/files?key=YOUR_API_KEY" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
-H "Content-Type: application/json" \
-d '{"file": {"display_name": "My Video"}}'
步骤 2:上传文件内容
# 提取上传 URL
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
# 上传文件
curl "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${VIDEO_PATH}"
完整脚本示例:
#!/bin/bash
API_KEY="YOUR_API_KEY"
FILE_PATH="/path/to/video.mp4"
DISPLAY_NAME="My Video"
# 获取文件信息
MIME_TYPE=$(file -b --mime-type "${FILE_PATH}")
NUM_BYTES=$(wc -c < "${FILE_PATH}")
echo "Uploading: ${FILE_PATH}"
echo "MIME Type: ${MIME_TYPE}"
echo "Size: ${NUM_BYTES} bytes"
# 步骤 1: 初始化上传
curl "http://your-api.com/upload/v1beta/files?key=${API_KEY}" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
-H "Content-Type: application/json" \
-d "{\"file\": {\"display_name\": \"${DISPLAY_NAME}\"}}"
# 步骤 2: 提取上传 URL
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
if [ -z "$upload_url" ]; then
echo "Error: Failed to get upload URL"
exit 1
fi
echo "Upload URL: ${upload_url}"
# 步骤 3: 上传文件
curl "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${FILE_PATH}" | jq .
# 清理
rm -f upload-header.tmp
curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
响应示例:
{
"files": [
{
"name": "files/abc-123",
"displayName": "My Document",
"mimeType": "video/mp4",
"sizeBytes": "12345",
"createTime": "2024-01-20T10:00:00Z",
"updateTime": "2024-01-20T10:00:00Z",
"expirationTime": "2024-01-22T10:00:00Z",
"uri": "https://generativelanguage.googleapis.com/v1beta/files/abc-123",
"state": "ACTIVE"
}
]
}
上传文件后,可以在 Gemini API 的 generateContent 请求中引用该文件:
#!/bin/bash
API_KEY="YOUR_API_KEY"
# 从文件列表中获取文件信息
FILE_INFO=$(curl -s "http://your-api.com/v1beta/files?key=${API_KEY}" | jq -r '.files[0]')
FILE_NAME=$(echo "$FILE_INFO" | jq -r '.name')
MIME_TYPE=$(echo "$FILE_INFO" | jq -r '.mimeType')
echo "Using file: $FILE_NAME"
echo "MIME type: $MIME_TYPE"
# 使用文件生成内容
curl "http://your-api.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${API_KEY}" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [{
"parts":[
{"fileData":{"mimeType": "'"${MIME_TYPE}"'", "fileUri": "'"${FILE_NAME}"'"}},
{"text": "请总结这个视频的内容"}
]
}]
}' | jq .
完整的上传和使用工作流:
#!/bin/bash
API_KEY="YOUR_API_KEY"
VIDEO_PATH="/path/to/video.mp4"
# ========== 第一步:上传视频文件 ==========
echo "=== Step 1: Uploading video ==="
MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}")
NUM_BYTES=$(wc -c < "${VIDEO_PATH}")
# 初始化上传
curl "http://your-api.com/upload/v1beta/files?key=${API_KEY}" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
-H "Content-Type: application/json" \
-d '{"file": {"display_name": "My Video"}}'
# 提取上传 URL
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
# 上传文件
UPLOAD_RESPONSE=$(curl -s "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${VIDEO_PATH}")
echo "$UPLOAD_RESPONSE" | jq .
# ========== 第二步:提取文件信息 ==========
FILE_NAME=$(echo "$UPLOAD_RESPONSE" | jq -r '.file.name')
FILE_MIME=$(echo "$UPLOAD_RESPONSE" | jq -r '.file.mimeType')
echo ""
echo "=== Step 2: File uploaded ==="
echo "File name: $FILE_NAME"
echo "MIME type: $FILE_MIME"
# ========== 第三步:使用文件生成内容 ==========
echo ""
echo "=== Step 3: Generating content ==="
curl "http://your-api.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${API_KEY}" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [{
"parts":[
{"fileData":{"mimeType": "'"${FILE_MIME}"'", "fileUri": "'"${FILE_NAME}"'"}},
{"text": "Summarize this video and create a quiz based on it."}
]
}]
}' | jq .
# 清理
rm -f upload-header.tmp
| 特性 | 简单上传 (Multipart) | 可恢复上传 (Resumable) |
|---|---|---|
| MIME 类型 | ❌ 通常为 application/octet-stream |
✅ 正确识别(如 video/mp4) |
| 文件大小限制 | 适合 < 100MB | ✅ 支持大文件 (< 500MB) |
| 上传步骤 | 一步完成 | 两步(初始化 + 上传) |
| 网络容错 | ❌ 失败需重新上传 | ✅ 支持断点续传(理论上) |
| 使用场景 | 小文件快速上传 | 视频、音频等大文件 |
| 推荐度 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
建议:
支持以下任意一种认证方式:
Authorization Header
-H "Authorization: Bearer YOUR_API_KEY"
bash
-H "x-goog-api-key: YOUR_API_KEY"
Query Parameter
?key=YOUR_API_KEY
如果需要支持大文件上传(超过默认限制),可以在 docker-compose.yml 或环境变量中配置:
environment:
- MAX_REQUEST_BODY_MB=500 # 支持最大 500MB 文件
或在启动时设置环境变量:
export MAX_REQUEST_BODY_MB=500
解决方案:
解决方案:
解决方案:
MAX_REQUEST_BODY_MB 配置原因:使用了简单上传 (Multipart) 方式
解决方案:
推荐:改用 Resumable Upload 方式
# 使用 Resumable Upload,自动设置正确的 MIME 类型
MIME_TYPE=$(file -b --mime-type "${FILE_PATH}")
# ... 按照 resumable upload 步骤上传
bash
curl -X POST "http://your-api.com/upload/v1beta/files?key=YOUR_API_KEY" \
-F "file=@video.mp4;type=video/mp4" \
-F "display_name=My Video"
原因:上传时的 MIME 类型与使用时不匹配
解决方案:
使用文件时,必须使用文件列表中返回的 mimeType,而不是猜测:
# 从文件列表获取正确的 MIME 类型
FILE_INFO=$(curl -s "http://your-api.com/v1beta/files?key=YOUR_API_KEY" | jq -r '.files[0]')
MIME_TYPE=$(echo "$FILE_INFO" | jq -r '.mimeType')
# 使用获取到的 MIME 类型
curl "http://your-api.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"contents": [{
"parts":[
{"fileData":{"mimeType": "'"${MIME_TYPE}"'", "fileUri": "files/abc-123"}}
]
}]
}'
controller/relay_gemini_file.go 中添加新的处理函数router/gemini_file_router.go 中注册新的路由relay/channel/gemini/file_helper.go 中添加辅助函数编辑 middleware/gemini_file_auth.go 中的 GeminiFileAuth 函数。
修改 middleware/gemini_file_auth.go 中的 findGeminiFileChannel 函数。
v1.1.0 (2026-01-20)
v1.0.0 (2026-01-20)