- 将 file 目录下的命名空间从 BuildFlow.Host.Endpoints.file 统一为 BuildFlow.Host.Endpoints.File - 将 im 目录下的命名空间从 BuildFlow.Host.Endpoints.im 统一为 BuildFlow.Host.Endpoints.IM - 将 rag 目录下的命名空间从 BuildFlow.Host.Endpoints.rag 统一为 BuildFlow.Host.Endpoints.Rag - 将 workflow 目录下的命名空间从 BuildFlow.Host.Endpoints.workflow 统一为 BuildFlow.Host.Endpoints.Workflow - 将 platform 目录下的命名空间从 BuildFlow.Host.Endpoints.rag 统一为 BuildFlow.Host.Endpoints.Platform - 修复了多个端点类的命名空间大小写不一致的问题
43 lines
1.6 KiB
C#
43 lines
1.6 KiB
C#
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");
|
||
}
|
||
|
||
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();
|
||
}
|
||
}
|
||
}
|