16 KiB
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 存储桶。
请求体
{
"bucket_name": "my-new-bucket"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| bucket_name | string | 是 | 存储桶名称(3-63字符,小写字母、数字、连字符) |
响应示例
成功 (200)
{
"success": true,
"message": "存储桶创建成功",
"bucket_name": "my-new-bucket"
}
存储桶已存在 (200)
{
"success": false,
"message": "存储桶已存在: my-new-bucket",
"bucket_name": "my-new-bucket"
}
cURL 示例
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 存储桶。支持强制删除(会先删除桶内所有文件)。
请求体
{
"bucket_name": "my-bucket",
"force": true
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| bucket_name | string | 是 | 存储桶名称 |
| force | boolean | 否 | 强制删除(默认 false,为 true 时会先删除桶内所有文件) |
响应示例
成功 (200)
{
"success": true,
"message": "存储桶删除成功",
"bucket_name": "my-bucket",
"files_deleted": 15
}
存储桶不存在 (200)
{
"success": false,
"message": "存储桶不存在: my-bucket",
"bucket_name": "my-bucket",
"files_deleted": 0
}
cURL 示例
# 普通删除(桶必须为空)
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 存储桶。
响应示例
{
"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 示例
curl -X GET "http://localhost:8000/api/v2/storage/buckets"
文件操作
4. 复制文件
POST /api/v2/storage/files/copy
在 MinIO 内复制文件。支持跨存储桶复制。
请求体
{
"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 | 否 | 目标存储桶(默认使用配置的默认桶) |
响应示例
{
"success": true,
"message": "文件复制成功",
"source_path": "docauditai/documents/contract.pdf",
"destination_path": "docauditai/backup/contract-2024.pdf"
}
cURL 示例
# 同桶内复制
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
移动文件(复制后删除源文件)。在同一目录内移动即为重命名。
请求体
{
"source_path": "documents/old-name.pdf",
"destination_path": "documents/new-name.pdf"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| source_path | string | 是 | 源文件路径 |
| destination_path | string | 是 | 目标文件路径 |
响应示例
{
"success": true,
"message": "文件移动成功",
"source_path": "documents/old-name.pdf",
"destination_path": "documents/new-name.pdf"
}
cURL 示例
# 重命名文件
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)
{
"success": true,
"message": "文件删除成功",
"file_path": "documents/old-file.pdf"
}
文件不存在 (200)
{
"success": false,
"message": "文件不存在: documents/old-file.pdf",
"file_path": "documents/old-file.pdf"
}
cURL 示例
curl -X DELETE "http://localhost:8000/api/v2/storage/files?file_path=documents/old-file.pdf"
7. 批量删除文件
POST /api/v2/storage/files/batch-delete
批量删除多个文件。
请求体
{
"file_paths": [
"temp/file1.pdf",
"temp/file2.pdf",
"temp/file3.pdf"
]
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file_paths | string[] | 是 | 文件路径列表(至少1个) |
响应示例
{
"success": true,
"message": "删除完成: 成功 3, 失败 0",
"deleted_count": 3,
"failed_count": 0,
"failed_paths": []
}
部分失败 (200)
{
"success": false,
"message": "删除完成: 成功 2, 失败 1",
"deleted_count": 2,
"failed_count": 1,
"failed_paths": ["temp/not-exist.pdf"]
}
cURL 示例
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 示例
# 下载文件
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 | 分页标记 |
响应示例
{
"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)
{
"success": true,
"message": "共 100 个文件",
"files": ["..."],
"total_count": 100,
"next_marker": "documents/file-100.pdf"
}
cURL 示例
# 列出根目录
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 | 是 | 文件路径 |
响应示例
{
"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 示例
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天) |
响应示例
{
"success": true,
"message": "获取成功",
"url": "http://minio:9000/docauditai/documents/contract.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...",
"expires_in": 3600
}
cURL 示例
# 默认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
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 组件示例
<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>
错误处理
所有接口返回统一格式:
{
"success": false,
"message": "错误描述信息"
}
常见错误
| 错误 | 说明 | 解决方案 |
|---|---|---|
| 存储桶不存在 | 操作的存储桶未找到 | 检查桶名是否正确 |
| 文件不存在 | 操作的文件路径无效 | 检查文件路径 |
| 存储桶非空 | 删除桶时桶内有文件 | 使用 force=true 强制删除 |
| 权限不足 | MinIO 访问凭证问题 | 检查配置的 access_key/secret_key |
测试
使用测试脚本进行完整测试:
python scripts/test_minio_api.py --host localhost --port 8000