如何在C# Minimal API中实现HTTP HEAD请求功能?
HEAD
HTTP HEAD方法请求的是:使用HTTP GET方法请求同一URL时会返回的响应头。
例如,若某个URL对应大文件下载,HEAD请求可读取Content-Length头信息来检查文件大小,无需实际下载文件。
问题描述
我需要在Minimal API端点中实现HEAD请求的支持,但测试时选择HEAD动词会返回错误:
405 Method Not Allowed
使用GET动词进行下载则正常工作。希望获得HEAD动词的实现示例或配置说明。
原GET端点代码如下:
app.MapGet(@"download/{fileName}", async (string fileName) => { var mimeType = "application/zip"; var path = @$"e:\{fileName}.zip"; var bytes = await File.ReadAllBytesAsync(path); return Results.File(bytes, mimeType, $"{fileName}.zip"); }) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound) .WithName($"GET {EndpointCategory} by Name") .WithTags(Tag);
解决方案
方式1:单独映射HEAD端点(推荐)
为同一个URL单独配置HEAD端点,仅处理响应头逻辑,避免读取整个文件内容:
// 保留原有的GET端点 app.MapGet(@"download/{fileName}", async (string fileName) => { var mimeType = "application/zip"; var path = @$"e:\{fileName}.zip"; if (!File.Exists(path)) { return Results.NotFound(); } var bytes = await File.ReadAllBytesAsync(path); return Results.File(bytes, mimeType, $"{fileName}.zip"); }) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound) .WithName($"GET {EndpointCategory} by Name") .WithTags(Tag); // 新增HEAD端点,仅返回响应头 app.MapHead(@"download/{fileName}", (string fileName) => { var mimeType = "application/zip"; var path = @$"e:\{fileName}.zip"; if (!File.Exists(path)) { return Results.NotFound(); } var fileInfo = new FileInfo(path); var responseHeaders = new Dictionary<string, string> { {"Content-Length", fileInfo.Length.ToString()}, {"Content-Type", mimeType} }; return Results.Ok().WithHeaders(responseHeaders); }) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound) .WithName($"HEAD {EndpointCategory} by Name") .WithTags(Tag);
方式2:让同一端点支持GET和HEAD
使用MapMethods指定允许的HTTP动词,ASP.NET会自动处理HEAD请求(仅返回响应头):
app.MapMethods(@"download/{fileName}", new[] { "GET", "HEAD" }, async (string fileName) => { var mimeType = "application/zip"; var path = @$"e:\{fileName}.zip"; if (!File.Exists(path)) { return Results.NotFound(); } var bytes = await File.ReadAllBytesAsync(path); return Results.File(bytes, mimeType, $"{fileName}.zip"); }) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound) .WithName($"{EndpointCategory} by Name") .WithTags(Tag);
注意:方式2虽然简便,但如果文件体积较大,GET逻辑中的File.ReadAllBytesAsync仍会将整个文件加载到内存,而HEAD请求不需要此操作。因此更推荐方式1,节省资源开销。
内容的提问来源于stack exchange,提问作者TheSloth
相关产品推荐
相关产品推荐

