6708c226a5
- 迁移 000023 gateway.file_objects(personal/system 归属隔离 + 部分索引) - internal/platform/storage:minio-go 适配(端点 scheme 剥离、流式 PutObject/Open/Delete) - internal/workbench/files.go:FileService(sha256 校验、PutObject-then-insert 回滚、delete 先删行再删对象) - admin /api/v1/admin/files + portal /api/v1/portal/files 处理器(流式上传下载、Content-Disposition) - RBAC file:read/file:manage;菜单加文件管理 + 门户文件仓库 - compose 增 minio 服务(S3_* anchor、不暴露端口);nginx client_max_body_size 32m→256m - 管理端文件管理页 + 门户个人文件仓;集成测试 TestFileObjectLifecycle 连真 MinIO 通过 - healthz object_storage:true;README/PRODUCTION/进展文档同步 Co-Authored-By: Claude <noreply@anthropic.com>
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import axios from 'axios'
|
|
import request from '@/utils/http'
|
|
import { useUserStore } from '@/store/modules/user'
|
|
|
|
export interface FileObject {
|
|
id: string
|
|
original_name: string
|
|
content_type: string
|
|
size_bytes: number
|
|
content_sha256: string
|
|
scope: string
|
|
owner_user_id?: string
|
|
created_by: string
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export const fetchFiles = () => request.get<FileObject[]>({ url: '/api/v1/admin/files' })
|
|
export const uploadFile = (file: File) => {
|
|
const form = new FormData()
|
|
form.append('file', file)
|
|
return request.post<FileObject>({ url: '/api/v1/admin/files', data: form, timeout: 120000 })
|
|
}
|
|
export const deleteFile = (id: string) => request.del({ url: `/api/v1/admin/files/${id}` })
|
|
|
|
// 文件体以 blob 流式下载,绕开统一响应拦截器(其期望 JSON envelope)。
|
|
export async function downloadFile(id: string, filename: string) {
|
|
const { accessToken } = useUserStore()
|
|
const token = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`
|
|
const res = await axios.get(`/api/v1/admin/files/${id}/download`, {
|
|
baseURL: import.meta.env.VITE_API_URL,
|
|
headers: { Authorization: token },
|
|
responseType: 'blob'
|
|
})
|
|
const url = URL.createObjectURL(res.data)
|
|
const anchor = document.createElement('a')
|
|
anchor.href = url
|
|
anchor.download = filename
|
|
anchor.click()
|
|
URL.revokeObjectURL(url)
|
|
}
|