Files
leaudit-platform-frontend/auth_doc/minio-api.md
T

777 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MinIO 存储管理 API 文档
## 概述
MinIO 存储管理模块提供对象存储的完整管理能力,包括存储桶管理和文件操作。
**基础路径**: `/api/v2/storage`
**认证要求**: 当前无需认证(后续可按需添加)
---
## 接口列表
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/buckets` | 创建存储桶 |
| DELETE | `/buckets` | 删除存储桶 |
| GET | `/buckets` | 列出所有存储桶 |
| POST | `/files/copy` | 复制文件 |
| POST | `/files/move` | 移动/重命名文件 |
| DELETE | `/files` | 删除单个文件 |
| POST | `/files/batch-delete` | 批量删除文件 |
| GET | `/files/download` | 下载文件 |
| GET | `/files` | 列出目录文件 |
| GET | `/files/metadata` | 获取文件元数据 |
| GET | `/files/presigned-url` | 获取预签名URL |
---
## 存储桶管理
### 1. 创建存储桶
**POST** `/api/v2/storage/buckets`
创建新的 MinIO 存储桶。
#### 请求体
```json
{
"bucket_name": "my-new-bucket"
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| bucket_name | string | 是 | 存储桶名称(3-63字符,小写字母、数字、连字符) |
#### 响应示例
**成功 (200)**
```json
{
"success": true,
"message": "存储桶创建成功",
"bucket_name": "my-new-bucket"
}
```
**存储桶已存在 (200)**
```json
{
"success": false,
"message": "存储桶已存在: my-new-bucket",
"bucket_name": "my-new-bucket"
}
```
#### cURL 示例
```bash
curl -X POST "http://localhost:8000/api/v2/storage/buckets" \
-H "Content-Type: application/json" \
-d '{"bucket_name": "my-new-bucket"}'
```
---
### 2. 删除存储桶
**DELETE** `/api/v2/storage/buckets`
删除 MinIO 存储桶。支持强制删除(会先删除桶内所有文件)。
#### 请求体
```json
{
"bucket_name": "my-bucket",
"force": true
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| bucket_name | string | 是 | 存储桶名称 |
| force | boolean | 否 | 强制删除(默认 false,为 true 时会先删除桶内所有文件) |
#### 响应示例
**成功 (200)**
```json
{
"success": true,
"message": "存储桶删除成功",
"bucket_name": "my-bucket",
"files_deleted": 15
}
```
**存储桶不存在 (200)**
```json
{
"success": false,
"message": "存储桶不存在: my-bucket",
"bucket_name": "my-bucket",
"files_deleted": 0
}
```
#### cURL 示例
```bash
# 普通删除(桶必须为空)
curl -X DELETE "http://localhost:8000/api/v2/storage/buckets" \
-H "Content-Type: application/json" \
-d '{"bucket_name": "my-bucket"}'
# 强制删除(会删除桶内所有文件)
curl -X DELETE "http://localhost:8000/api/v2/storage/buckets" \
-H "Content-Type: application/json" \
-d '{"bucket_name": "my-bucket", "force": true}'
```
---
### 3. 列出存储桶
**GET** `/api/v2/storage/buckets`
列出所有 MinIO 存储桶。
#### 响应示例
```json
{
"success": true,
"message": "共 3 个存储桶",
"buckets": [
{
"name": "docauditai",
"creation_date": "2024-01-15T08:30:00+00:00"
},
{
"name": "backup",
"creation_date": "2024-02-20T10:15:00+00:00"
},
{
"name": "temp",
"creation_date": "2024-03-01T14:00:00+00:00"
}
]
}
```
#### cURL 示例
```bash
curl -X GET "http://localhost:8000/api/v2/storage/buckets"
```
---
## 文件操作
### 4. 复制文件
**POST** `/api/v2/storage/files/copy`
在 MinIO 内复制文件。支持跨存储桶复制。
#### 请求体
```json
{
"source_path": "documents/contract.pdf",
"destination_path": "backup/contract-2024.pdf",
"source_bucket": null,
"destination_bucket": null
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| source_path | string | 是 | 源文件路径 |
| destination_path | string | 是 | 目标文件路径 |
| source_bucket | string | 否 | 源存储桶(默认使用配置的默认桶) |
| destination_bucket | string | 否 | 目标存储桶(默认使用配置的默认桶) |
#### 响应示例
```json
{
"success": true,
"message": "文件复制成功",
"source_path": "docauditai/documents/contract.pdf",
"destination_path": "docauditai/backup/contract-2024.pdf"
}
```
#### cURL 示例
```bash
# 同桶内复制
curl -X POST "http://localhost:8000/api/v2/storage/files/copy" \
-H "Content-Type: application/json" \
-d '{
"source_path": "documents/contract.pdf",
"destination_path": "backup/contract-2024.pdf"
}'
# 跨桶复制
curl -X POST "http://localhost:8000/api/v2/storage/files/copy" \
-H "Content-Type: application/json" \
-d '{
"source_path": "documents/contract.pdf",
"destination_path": "contract.pdf",
"source_bucket": "docauditai",
"destination_bucket": "backup"
}'
```
---
### 5. 移动/重命名文件
**POST** `/api/v2/storage/files/move`
移动文件(复制后删除源文件)。在同一目录内移动即为重命名。
#### 请求体
```json
{
"source_path": "documents/old-name.pdf",
"destination_path": "documents/new-name.pdf"
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| source_path | string | 是 | 源文件路径 |
| destination_path | string | 是 | 目标文件路径 |
#### 响应示例
```json
{
"success": true,
"message": "文件移动成功",
"source_path": "documents/old-name.pdf",
"destination_path": "documents/new-name.pdf"
}
```
#### cURL 示例
```bash
# 重命名文件
curl -X POST "http://localhost:8000/api/v2/storage/files/move" \
-H "Content-Type: application/json" \
-d '{
"source_path": "documents/report-v1.pdf",
"destination_path": "documents/report-v2.pdf"
}'
# 移动到其他目录
curl -X POST "http://localhost:8000/api/v2/storage/files/move" \
-H "Content-Type: application/json" \
-d '{
"source_path": "temp/upload.pdf",
"destination_path": "documents/final.pdf"
}'
```
---
### 6. 删除单个文件
**DELETE** `/api/v2/storage/files`
删除 MinIO 中的单个文件。
#### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| file_path | string | 是 | 文件路径 |
#### 响应示例
**成功 (200)**
```json
{
"success": true,
"message": "文件删除成功",
"file_path": "documents/old-file.pdf"
}
```
**文件不存在 (200)**
```json
{
"success": false,
"message": "文件不存在: documents/old-file.pdf",
"file_path": "documents/old-file.pdf"
}
```
#### cURL 示例
```bash
curl -X DELETE "http://localhost:8000/api/v2/storage/files?file_path=documents/old-file.pdf"
```
---
### 7. 批量删除文件
**POST** `/api/v2/storage/files/batch-delete`
批量删除多个文件。
#### 请求体
```json
{
"file_paths": [
"temp/file1.pdf",
"temp/file2.pdf",
"temp/file3.pdf"
]
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| file_paths | string[] | 是 | 文件路径列表(至少1个) |
#### 响应示例
```json
{
"success": true,
"message": "删除完成: 成功 3, 失败 0",
"deleted_count": 3,
"failed_count": 0,
"failed_paths": []
}
```
**部分失败 (200)**
```json
{
"success": false,
"message": "删除完成: 成功 2, 失败 1",
"deleted_count": 2,
"failed_count": 1,
"failed_paths": ["temp/not-exist.pdf"]
}
```
#### cURL 示例
```bash
curl -X POST "http://localhost:8000/api/v2/storage/files/batch-delete" \
-H "Content-Type: application/json" \
-d '{
"file_paths": [
"temp/file1.pdf",
"temp/file2.pdf",
"temp/file3.pdf"
]
}'
```
---
### 8. 下载文件
**GET** `/api/v2/storage/files/download`
从 MinIO 下载文件。返回文件流。
#### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| file_path | string | 是 | 文件路径 |
| filename | string | 否 | 下载时显示的文件名 |
#### 响应
返回文件二进制流,包含以下响应头:
```
Content-Type: application/pdf
Content-Disposition: attachment; filename="contract.pdf"
Content-Length: 1234567
```
#### cURL 示例
```bash
# 下载文件
curl -X GET "http://localhost:8000/api/v2/storage/files/download?file_path=documents/contract.pdf" \
-o contract.pdf
# 指定下载文件名
curl -X GET "http://localhost:8000/api/v2/storage/files/download?file_path=documents/contract.pdf&filename=my-contract.pdf" \
-o my-contract.pdf
```
#### 浏览器直接下载
```
http://localhost:8000/api/v2/storage/files/download?file_path=documents/contract.pdf
```
---
### 9. 列出目录文件
**GET** `/api/v2/storage/files`
列出指定目录下的文件。
#### 请求参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| directory_path | string | 否 | "" | 目录路径 |
| recursive | boolean | 否 | false | 是否递归列出子目录 |
| max_files | int | 否 | 100 | 最大返回数量(1-1000 |
| marker | string | 否 | null | 分页标记 |
#### 响应示例
```json
{
"success": true,
"message": "共 5 个文件",
"files": [
"documents/contract-001.pdf",
"documents/contract-002.pdf",
"documents/contract-003.pdf",
"documents/report.docx",
"documents/summary.xlsx"
],
"total_count": 5,
"next_marker": null
}
```
**分页响应 (200)**
```json
{
"success": true,
"message": "共 100 个文件",
"files": ["..."],
"total_count": 100,
"next_marker": "documents/file-100.pdf"
}
```
#### cURL 示例
```bash
# 列出根目录
curl -X GET "http://localhost:8000/api/v2/storage/files"
# 列出指定目录
curl -X GET "http://localhost:8000/api/v2/storage/files?directory_path=documents"
# 递归列出
curl -X GET "http://localhost:8000/api/v2/storage/files?directory_path=documents&recursive=true"
# 分页查询
curl -X GET "http://localhost:8000/api/v2/storage/files?directory_path=documents&max_files=50"
# 获取下一页
curl -X GET "http://localhost:8000/api/v2/storage/files?directory_path=documents&max_files=50&marker=documents/file-50.pdf"
```
---
### 10. 获取文件元数据
**GET** `/api/v2/storage/files/metadata`
获取文件的详细元数据信息。
#### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| file_path | string | 是 | 文件路径 |
#### 响应示例
```json
{
"success": true,
"message": "获取成功",
"file_info": {
"path": "documents/contract.pdf",
"size": 1234567,
"content_type": "application/pdf",
"created_time": "2024-03-15T10:30:00+00:00",
"modified_time": "2024-03-15T10:30:00+00:00",
"etag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"url": "http://minio:9000/docauditai/documents/contract.pdf?X-Amz-..."
}
}
```
#### cURL 示例
```bash
curl -X GET "http://localhost:8000/api/v2/storage/files/metadata?file_path=documents/contract.pdf"
```
---
### 11. 获取预签名URL
**GET** `/api/v2/storage/files/presigned-url`
获取文件的预签名下载URL,可用于临时分享。
#### 请求参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| file_path | string | 是 | - | 文件路径 |
| expires | int | 否 | 3600 | 过期时间(秒),范围 60-604800(7天) |
#### 响应示例
```json
{
"success": true,
"message": "获取成功",
"url": "http://minio:9000/docauditai/documents/contract.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...",
"expires_in": 3600
}
```
#### cURL 示例
```bash
# 默认1小时过期
curl -X GET "http://localhost:8000/api/v2/storage/files/presigned-url?file_path=documents/contract.pdf"
# 自定义过期时间(1天)
curl -X GET "http://localhost:8000/api/v2/storage/files/presigned-url?file_path=documents/contract.pdf&expires=86400"
# 最长7天
curl -X GET "http://localhost:8000/api/v2/storage/files/presigned-url?file_path=documents/contract.pdf&expires=604800"
```
---
## 前端集成示例
### JavaScript/Fetch
```javascript
const API_BASE = 'http://localhost:8000/api/v2/storage';
// 列出存储桶
async function listBuckets() {
const response = await fetch(`${API_BASE}/buckets`);
return response.json();
}
// 创建存储桶
async function createBucket(bucketName) {
const response = await fetch(`${API_BASE}/buckets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bucket_name: bucketName })
});
return response.json();
}
// 复制文件
async function copyFile(sourcePath, destPath) {
const response = await fetch(`${API_BASE}/files/copy`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
source_path: sourcePath,
destination_path: destPath
})
});
return response.json();
}
// 重命名文件
async function renameFile(oldPath, newPath) {
const response = await fetch(`${API_BASE}/files/move`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
source_path: oldPath,
destination_path: newPath
})
});
return response.json();
}
// 删除文件
async function deleteFile(filePath) {
const response = await fetch(
`${API_BASE}/files?file_path=${encodeURIComponent(filePath)}`,
{ method: 'DELETE' }
);
return response.json();
}
// 下载文件
function downloadFile(filePath, filename) {
const url = `${API_BASE}/files/download?file_path=${encodeURIComponent(filePath)}`;
if (filename) {
url += `&filename=${encodeURIComponent(filename)}`;
}
window.open(url, '_blank');
}
// 获取文件列表
async function listFiles(directory = '', recursive = false) {
const params = new URLSearchParams({
directory_path: directory,
recursive: recursive.toString()
});
const response = await fetch(`${API_BASE}/files?${params}`);
return response.json();
}
// 获取预签名URL
async function getPresignedUrl(filePath, expires = 3600) {
const params = new URLSearchParams({
file_path: filePath,
expires: expires.toString()
});
const response = await fetch(`${API_BASE}/files/presigned-url?${params}`);
return response.json();
}
```
### Vue 3 组件示例
```vue
<template>
<div class="file-manager">
<div class="file-list">
<div v-for="file in files" :key="file" class="file-item">
<span>{{ file }}</span>
<div class="actions">
<button @click="handleDownload(file)">下载</button>
<button @click="handleRename(file)">重命名</button>
<button @click="handleDelete(file)">删除</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const API_BASE = '/api/v2/storage';
const files = ref([]);
onMounted(async () => {
await loadFiles();
});
async function loadFiles() {
const response = await fetch(`${API_BASE}/files?directory_path=documents&recursive=true`);
const data = await response.json();
if (data.success) {
files.value = data.files;
}
}
function handleDownload(filePath) {
window.open(`${API_BASE}/files/download?file_path=${encodeURIComponent(filePath)}`);
}
async function handleRename(filePath) {
const newName = prompt('请输入新文件名:');
if (!newName) return;
const directory = filePath.substring(0, filePath.lastIndexOf('/'));
const newPath = `${directory}/${newName}`;
const response = await fetch(`${API_BASE}/files/move`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
source_path: filePath,
destination_path: newPath
})
});
const data = await response.json();
if (data.success) {
await loadFiles();
} else {
alert(data.message);
}
}
async function handleDelete(filePath) {
if (!confirm(`确定删除 ${filePath}`)) return;
const response = await fetch(
`${API_BASE}/files?file_path=${encodeURIComponent(filePath)}`,
{ method: 'DELETE' }
);
const data = await response.json();
if (data.success) {
await loadFiles();
} else {
alert(data.message);
}
}
</script>
```
---
## 错误处理
所有接口返回统一格式:
```json
{
"success": false,
"message": "错误描述信息"
}
```
### 常见错误
| 错误 | 说明 | 解决方案 |
|------|------|----------|
| 存储桶不存在 | 操作的存储桶未找到 | 检查桶名是否正确 |
| 文件不存在 | 操作的文件路径无效 | 检查文件路径 |
| 存储桶非空 | 删除桶时桶内有文件 | 使用 force=true 强制删除 |
| 权限不足 | MinIO 访问凭证问题 | 检查配置的 access_key/secret_key |
---
## 测试
使用测试脚本进行完整测试:
```bash
python scripts/test_minio_api.py --host localhost --port 8000
```