Преглед изворни кода

docs: update Gemini File API documentation with resumable upload

- Add detailed documentation for two upload methods
- Add resumable upload step-by-step guide with complete examples
- Add comparison table between multipart and resumable upload
- Add complete workflow example (upload + use file)
- Add MIME type troubleshooting section
- Update features and version history
- Include recommendations for different file types
supeng пре 1 месец
родитељ
комит
0cae7234ee
1 измењених фајлова са 268 додато и 3 уклоњено
  1. 268 3
      docs/GEMINI_FILE_API.md

+ 268 - 3
docs/GEMINI_FILE_API.md

@@ -44,12 +44,103 @@ Gemini File API 是一个完全独立的模块,与其他 API 逻辑完全隔
 ## 使用方式
 ## 使用方式
 
 
 ### 1. 上传文件
 ### 1. 上传文件
+
+本模块支持两种上传方式:
+
+#### 方式 1:简单上传(Multipart Upload)
+
+适合小文件(< 100MB),一次性上传。
+
 ```bash
 ```bash
 curl -X POST "http://your-api.com/upload/v1beta/files?key=YOUR_API_KEY" \
 curl -X POST "http://your-api.com/upload/v1beta/files?key=YOUR_API_KEY" \
   -F "file=@/path/to/file.pdf" \
   -F "file=@/path/to/file.pdf" \
   -F "display_name=My Document"
   -F "display_name=My Document"
 ```
 ```
 
 
+**注意**:此方式可能无法正确设置 MIME 类型,文件会被标记为 `application/octet-stream`。
+
+#### 方式 2:可恢复上传(Resumable Upload)⭐ 推荐
+
+适合大文件或需要正确 MIME 类型的场景。分为两步:
+
+**步骤 1:初始化上传会话**
+```bash
+# 自动获取文件信息
+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:上传文件内容**
+```bash
+# 提取上传 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}"
+```
+
+**完整脚本示例**:
+```bash
+#!/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
+```
+
 ### 2. 列出文件
 ### 2. 列出文件
 ```bash
 ```bash
 curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
 curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
@@ -62,16 +153,131 @@ curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
     {
     {
       "name": "files/abc-123",
       "name": "files/abc-123",
       "displayName": "My Document",
       "displayName": "My Document",
-      "mimeType": "application/pdf",
+      "mimeType": "video/mp4",
       "sizeBytes": "12345",
       "sizeBytes": "12345",
       "createTime": "2024-01-20T10:00:00Z",
       "createTime": "2024-01-20T10:00:00Z",
       "updateTime": "2024-01-20T10:00:00Z",
       "updateTime": "2024-01-20T10:00:00Z",
-      "uri": "https://generativelanguage.googleapis.com/v1beta/files/abc-123"
+      "expirationTime": "2024-01-22T10:00:00Z",
+      "uri": "https://generativelanguage.googleapis.com/v1beta/files/abc-123",
+      "state": "ACTIVE"
     }
     }
   ]
   ]
 }
 }
 ```
 ```
 
 
+### 3. 使用上传的文件生成内容
+
+上传文件后,可以在 Gemini API 的 `generateContent` 请求中引用该文件:
+
+```bash
+#!/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 .
+```
+
+**完整的上传和使用工作流**:
+
+```bash
+#!/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) |
+| **上传步骤** | 一步完成 | 两步(初始化 + 上传) |
+| **网络容错** | ❌ 失败需重新上传 | ✅ 支持断点续传(理论上) |
+| **使用场景** | 小文件快速上传 | 视频、音频等大文件 |
+| **推荐度** | ⭐⭐ | ⭐⭐⭐⭐⭐ |
+
+**建议**:
+- 📹 **视频文件**:必须使用 Resumable Upload
+- 🎵 **音频文件**:推荐使用 Resumable Upload
+- 📄 **文档文件**:两种方式都可以
+- 🖼️ **图片文件**:两种方式都可以
+
 ## 认证方式
 ## 认证方式
 
 
 支持以下任意一种认证方式:
 支持以下任意一种认证方式:
@@ -99,6 +305,16 @@ curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
 - 独立的中间件链
 - 独立的中间件链
 - 不影响其他 API 功能
 - 不影响其他 API 功能
 
 
+### ✅ 两种上传方式
+- **简单上传 (Multipart)**:适合小文件,一步完成
+- **可恢复上传 (Resumable)**:适合大文件,正确设置 MIME 类型
+
+### ✅ 正确的 MIME 类型支持
+- 自动识别视频文件(video/mp4, video/quicktime 等)
+- 自动识别音频文件(audio/mpeg, audio/wav 等)
+- 支持文档、图片等各种文件类型
+- 确保 Gemini 能正确处理文件
+
 ### ✅ 自动渠道选择
 ### ✅ 自动渠道选择
 - 自动查找可用的 Gemini 渠道
 - 自动查找可用的 Gemini 渠道
 - 支持多个 Gemini 模型作为备选
 - 支持多个 Gemini 模型作为备选
@@ -107,10 +323,12 @@ curl "http://your-api.com/v1beta/files?key=YOUR_API_KEY"
 ### ✅ 多种认证方式
 ### ✅ 多种认证方式
 - 灵活的认证方式支持
 - 灵活的认证方式支持
 - 兼容 OpenAI、Gemini、Claude 等多种 API 风格
 - 兼容 OpenAI、Gemini、Claude 等多种 API 风格
+- 支持 Authorization header、x-goog-api-key、query parameter
 
 
 ### ✅ 大文件支持
 ### ✅ 大文件支持
 - 支持最大 500MB 的文件上传
 - 支持最大 500MB 的文件上传
 - 流式传输,内存占用低
 - 流式传输,内存占用低
+- 适合视频、音频等大型媒体文件
 
 
 ## 配置
 ## 配置
 
 
@@ -161,6 +379,46 @@ export MAX_REQUEST_BODY_MB=500
 2. 确认 `MAX_REQUEST_BODY_MB` 配置
 2. 确认 `MAX_REQUEST_BODY_MB` 配置
 3. 验证 Gemini API Key 权限
 3. 验证 Gemini API Key 权限
 
 
+### 问题: 文件 MIME 类型不正确(显示为 application/octet-stream)
+**原因**:使用了简单上传 (Multipart) 方式
+
+**解决方案**:
+1. **推荐**:改用 Resumable Upload 方式
+   ```bash
+   # 使用 Resumable Upload,自动设置正确的 MIME 类型
+   MIME_TYPE=$(file -b --mime-type "${FILE_PATH}")
+   # ... 按照 resumable upload 步骤上传
+   ```
+
+2. 或者在 multipart 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"
+   ```
+
+### 问题: 使用文件时报错 "expected application/octet-stream"
+**原因**:上传时的 MIME 类型与使用时不匹配
+
+**解决方案**:
+使用文件时,必须使用文件列表中返回的 `mimeType`,而不是猜测:
+```bash
+# 从文件列表获取正确的 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"}}
+      ]
+    }]
+  }'
+```
+
 ## 开发指南
 ## 开发指南
 
 
 ### 添加新的文件操作
 ### 添加新的文件操作
@@ -179,9 +437,16 @@ export MAX_REQUEST_BODY_MB=500
 
 
 ## 版本历史
 ## 版本历史
 
 
+- **v1.1.0** (2026-01-20)
+  - ✅ 新增支持 Resumable Upload Protocol
+  - ✅ 正确设置文件 MIME 类型(video/mp4、audio/mpeg 等)
+  - ✅ 支持两种上传方式:简单上传和可恢复上传
+  - ✅ 保持向后兼容
+  - ✅ 完善文档和使用示例
+
 - **v1.0.0** (2026-01-20)
 - **v1.0.0** (2026-01-20)
   - 初始版本
   - 初始版本
   - 完全独立的模块架构
   - 完全独立的模块架构
-  - 支持文件上传、列表、获取、删除操作
+  - 支持文件上传和列表操作
   - 多种认证方式支持
   - 多种认证方式支持
   - 自动渠道选择
   - 自动渠道选择