文件管理系统 API 文档
大约 4 分钟
文件管理系统 API 文档
概述
本文档描述了文件管理系统的 gRPC API 接口,涵盖文件的上传、下载、删除、元数据管理、URL 生成等功能。
包信息
- 包名:
filemanager - Go 包:
filemanager - 语法版本:
proto3
导入依赖
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";通用消息类型
FileMetadata
文件元数据
| 字段 | 类型 | 描述 |
|---|---|---|
| file_name | string | 文件名 |
| file_size | int64 | 文件大小(字节) |
| content_type | string | MIME 类型 |
| description | string | 文件描述 |
| directory | string | 存储目录 |
| tags | map<string, string> | 标签(键值对) |
| hash | string | 客户端计算的哈希(可选) |
| publicly_accessible | bool | 是否允许公开访问 |
| custom_url_path | string | 自定义 URL 路径(可选) |
FileRequest
文件标识(ID 或路径二选一)
| 字段 | 类型 | 描述 |
|---|---|---|
| file_id | string | 文件唯一 ID |
| file_path | string | 文件路径(目录+文件名) |
FileChunk
下载文件的数据块
| 字段 | 类型 | 描述 |
|---|---|---|
| content | bytes | 文件内容块 |
| position | int64 | 字节偏移量 |
| is_last_chunk | bool | 是否最后一个块 |
FileInfo
文件信息
| 字段 | 类型 | 描述 |
|---|---|---|
| file_id | string | 文件 ID |
| file_name | string | 文件名 |
| file_path | string | 文件完整路径 |
| file_size | int64 | 文件大小 |
| content_type | string | MIME 类型 |
| created_at | google.protobuf.Timestamp | 创建时间 |
| updated_at | google.protobuf.Timestamp | 更新时间 |
| hash | string | 哈希值 |
| status | string | 文件状态(正常、归档、删除) |
| tags | map<string, string> | 标签 |
| description | string | 描述 |
| publicly_accessible | bool | 是否公开访问 |
| url | string | 相对 URL |
| full_url | string | 含域名 URL |
| url_expires_at | google.protobuf.Timestamp | URL 过期时间(如适用) |
FileResponse
文件操作结果
| 字段 | 类型 | 描述 |
|---|---|---|
| success | bool | 是否成功 |
| message | string | 消息 |
| file_id | string | 文件 ID |
| file_info | FileInfo | 文件信息 |
FileOperationResponse
通用操作结果
| 字段 | 类型 | 描述 |
|---|---|---|
| success | bool | 是否成功 |
| message | string | 消息 |
| file_id | string | 文件 ID |
ListFilesRequest / ListFilesResponse
分页与过滤列出文件
message ListFilesRequest {
string directory = 1; // 目录
int32 page_size = 2; // 每页数量
int32 page_number = 3; // 页码(从 1 开始)
string filter = 4; // 过滤条件(如 "*.txt")
string sort_by = 5; // 排序字段(name/size/created_at)
bool ascending = 6; // 是否升序
map<string, string> tags_filter = 7; // 标签过滤
}
message ListFilesResponse {
repeated FileInfo files = 1; // 文件列表
int32 total_files = 2; // 总文件数
int32 total_pages = 3; // 总页数
int32 current_page = 4; // 当前页码
}UpdateFileMetadataRequest
更新文件元数据
message UpdateFileMetadataRequest {
string file_id = 1;
string new_name = 2;
string new_directory = 3;
string description = 4;
map<string, string> tags = 5;
bool append_tags = 6;
bool publicly_accessible = 7;
string custom_url_path = 8;
}ExistsResponse
| 字段 | 类型 | 描述 |
|---|---|---|
| exists | bool | 是否存在 |
| file_id | string | 存在则返回文件 ID |
| file_path | string | 存在则返回文件路径 |
| url | string | 如可访问,返回 URL |
HashResponse
| 字段 | 类型 | 描述 |
|---|---|---|
| file_id | string | 文件 ID |
| hash_value | string | 哈希值 |
| algorithm | string | 算法(如 SHA-256) |
FileUrlRequest / TemporaryFileUrlRequest / FileUrlResponse
message FileUrlRequest {
oneof identifier { string file_id = 1; string file_path = 2; }
bool refresh = 3; // 是否刷新 URL
}
message TemporaryFileUrlRequest {
oneof identifier { string file_id = 1; string file_path = 2; }
int64 expiration_seconds = 3; // 过期秒数
}
message FileUrlResponse {
bool success = 1;
string message = 2;
string file_id = 3;
string url = 4;
google.protobuf.Timestamp expires_at = 5;
bool is_public = 6;
}服务接口
服务名:FileManagerService
1. 上传文件(客户端流)UploadFile
请求:
rpc UploadFile (stream FileUploadRequest) returns (FileResponse);FileUploadRequest:
message FileUploadRequest {
oneof data {
FileMetadata metadata = 1; // 首帧发送
bytes content_chunk = 2; // 后续分片
}
}响应:FileResponse
2. 下载文件(服务端流)DownloadFile
请求:FileRequest
响应:
rpc DownloadFile (FileRequest) returns (stream FileChunk);3. 删除文件 DeleteFile
请求:FileRequest
响应:FileOperationResponse
4. 获取文件信息 GetFileInfo
请求:FileRequest
响应:FileInfo
5. 列出文件 ListFiles
请求:ListFilesRequest
响应:ListFilesResponse
6. 更新文件元数据 UpdateFileMetadata
请求:UpdateFileMetadataRequest
响应:FileResponse
7. 文件是否存在 FileExists
请求:FileRequest
响应:ExistsResponse
8. 计算文件哈希 CalculateFileHash
请求:FileRequest
响应:HashResponse
9. 获取文件 URL GetFileUrl
请求:FileUrlRequest
响应:FileUrlResponse
10. 生成临时 URL GenerateTemporaryFileUrl
请求:TemporaryFileUrlRequest
响应:FileUrlResponse
状态码说明
| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 403 | 权限不足 |
| 404 | 资源不存在 |
| 409 | 冲突(如重名、哈希不一致) |
| 500 | 服务器内部错误 |
使用示例(Go)
以下示例仅演示客户端调用方式,需将
pb包路径替换为实际生成路径。
上传文件(流式)
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
cli := pb.NewFileManagerServiceClient(conn)
ctx := context.Background()
stream, _ := cli.UploadFile(ctx)
// 1) 发送元数据
_ = stream.Send(&pb.FileUploadRequest{Data: &pb.FileUploadRequest_Metadata{Metadata: &pb.FileMetadata{
FileName: "report.pdf",
ContentType: "application/pdf",
Directory: "/docs",
PubliclyAccessible: true,
}}})
// 2) 分片发送内容(示意)
for _, chunk := range [][]byte{part1, part2, part3} {
_ = stream.Send(&pb.FileUploadRequest{Data: &pb.FileUploadRequest_ContentChunk{ContentChunk: chunk}})
}
resp, _ := stream.CloseAndRecv()
fmt.Println("上传结果:", resp.Success, resp.FileId)下载文件(流式)
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
cli := pb.NewFileManagerServiceClient(conn)
stream, _ := cli.DownloadFile(context.Background(), &pb.FileRequest{Identifier: &pb.FileRequest_FileId{FileId: "fid_123"}})
for {
chunk, err := stream.Recv()
if err == io.EOF { break }
if err != nil { log.Fatal(err) }
// 处理 chunk.Content
}获取文件 URL
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
cli := pb.NewFileManagerServiceClient(conn)
rsp, err := cli.GetFileUrl(context.Background(), &pb.FileUrlRequest{Identifier: &pb.FileUrlRequest_FileId{FileId: "fid_123"}})
if err != nil { log.Fatal(err) }
fmt.Println("URL:", rsp.Url)列出文件
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
cli := pb.NewFileManagerServiceClient(conn)
resp, err := cli.ListFiles(context.Background(), &pb.ListFilesRequest{Directory: "/docs", PageSize: 20, PageNumber: 1})
if err != nil { log.Fatal(err) }
for _, f := range resp.Files { fmt.Println(f.FileName, f.FileSize) }删除文件
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
cli := pb.NewFileManagerServiceClient(conn)
resp, err := cli.DeleteFile(context.Background(), &pb.FileRequest{Identifier: &pb.FileRequest_FilePath{FilePath: "/docs/report.pdf"}})
if err != nil { log.Fatal(err) }
fmt.Println("删除:", resp.Success)代码生成(Go)
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
file_manager.proto注意事项
- 上传请先发送
FileMetadata,再发送内容分片。 - 建议为大文件分片(如 1MB),并在服务端合并校验哈希。
- 公开访问需审慎使用,结合临时 URL 与过期策略。
custom_url_path需确保唯一性并避免敏感信息暴露。- 生产环境建议开启 TLS 并启用鉴权。