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

16 KiB
Raw Blame History

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