build-flow.api/src/BuildFlow.Host/Endpoints/file/Files/GetFilePreviewEndpoint.cs
xiangning 2181f7dd49 feat(platform): 完善平台功能与权限管理
- 在菜单系统中新增 RenderType、FormDefinitionId 和 RuntimeViewMode 字段
- 实现自定义表单菜单类型的组件映射和验证逻辑
- 为分片上传相关端点添加 file:upload 权限控制
- 为桶和文件夹操作添加 bucket:write 和 file:write 权限控制
- 为文件共享功能添加 file-share:write 权限控制
- 为文件读取操作添加 file:read 权限控制
- 扩展 AI 模型提供商枚举,支持更多模型供应商
- 在 AI 模型创建和更新时添加枚举值验证
- 重构工作流按钮权限检查逻辑,使用统一的权限码查询方式
- 为 JSON 格式文档添加提取器支持
- 增强表单数据派生服务,支持自定义表单关联解析
- 为表单数据添加按表单定义 ID 的索引优化
- 添加聊天消息搜索和上下文获取的集成测试
- 修正删除菜单端点的 ID 类型从 Guid 改为 long
2026-07-04 19:38:43 +08:00

44 lines
1.7 KiB
C#
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.

using System.Net.Mime;
using File.Application.Features.Files.Queries;
using MediatR;
namespace BuildFlow.Host.Endpoints.File.Files;
/// <summary>
/// 文件预览端点。GET /api/files/preview,流式返回文件内容供内联展示(非下载)。
/// 后端从 S3 拉流透传,前端永远不接触 S3 URL 和凭据。
/// 鉴权:[Authorize] + JWT 中间件从 token query 参数读 JWT(img src / window.open 无法带 header)。
/// 该路径在 ApiResponseMiddlewareOptions.PassthroughPrefixes 注册,绕过响应包裹中间件的缓冲。
/// </summary>
[Authorize]
public class GetFilePreviewEndpoint(IMediator mediator) : Endpoint<GetFilePreviewRequest>
{
public override void Configure()
{
Get("/files/preview");
Permissions("file:read");
}
public override async Task HandleAsync(GetFilePreviewRequest req, CancellationToken ct)
{
// 复用下载查询(返回 Stream + ContentType + FileName)
var result = await mediator.Send(new DownloadFileQuery(req.ObjectKey), ct);
// inline = 浏览器内联展示(图片/PDF 直接渲染),而非触发下载
HttpContext.Response.ContentType = result.ContentType;
var disposition = new ContentDisposition { FileName = result.FileName, Inline = true };
HttpContext.Response.Headers.ContentDisposition = disposition.ToString();
// 流式透传:S3 流 → HTTP 响应体
try
{
await result.Stream.CopyToAsync(HttpContext.Response.Body, ct);
await HttpContext.Response.Body.FlushAsync(ct);
}
finally
{
await result.Stream.DisposeAsync();
}
}
}