如何在HttpSelfHostServer中实现Web API的图片访问功能?
在HttpSelfHostServer中实现静态图片访问
HttpSelfHostServer没有OWIN生态中的UseFileServer这类静态资源处理扩展,需要手动实现静态图片的访问逻辑,下面提供两种可行方案:
方案一:通过ApiController处理静态图片请求
步骤1:创建静态文件控制器
新增一个ImagesController,负责读取本地图片并返回响应:
using System.IO; using System.Net; using System.Net.Http; using System.Web.Http; namespace WebAPIServerV2.Controllers { public class ImagesController : ApiController { // 本地图片存储根路径,可根据实际场景调整 private readonly string _imageRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images"); [HttpGet] public HttpResponseMessage Get(string filename) { var filePath = Path.Combine(_imageRoot, filename); if (!File.Exists(filePath)) { return Request.CreateResponse(HttpStatusCode.NotFound); } var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(fileStream) }; // 根据文件扩展名设置正确的Content-Type var ext = Path.GetExtension(filename).ToLowerInvariant(); switch (ext) { case ".jpg": case ".jpeg": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg"); break; case ".png": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png"); break; case ".gif": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); break; default: response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); break; } return response; } } }
步骤2:添加静态资源路由
在Start方法中,新增匹配images/{filename}的路由(需放在原有API路由之前,避免被拦截):
public void Start(string url) { if (m_Server != null) { Stop(); } var config = new HttpSelfHostConfiguration(url); config.DependencyResolver = new AutofacWebApiDependencyResolver(m_lifetimeScope); config.MaxReceivedMessageSize = int.MaxValue; // 静态图片路由 config.Routes.MapHttpRoute( name: "StaticImages", routeTemplate: "images/{filename}", defaults: new { controller = "Images", action = "Get" } ); // 原有API路由 config.Routes.MapHttpRoute( name: "ServerAPI", routeTemplate: "server/{controller}/{action}" ); // 原有格式化配置 config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter()); config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; m_Server = new HttpSelfHostServer(config); m_Server.OpenAsync().Wait(); if (Environment.UserInteractive) Console.WriteLine($"WebAPI server start at:{url}"); }
注意事项
- 确保项目根目录下存在
Images文件夹,或修改_imageRoot指向实际存储路径 - 保证应用程序对目标文件夹有读取权限
- 可扩展逻辑添加缓存头、文件大小限制等优化
方案二:自定义HttpMessageHandler处理静态资源
若不想通过控制器,可直接在消息处理层拦截静态资源请求:
步骤1:创建静态文件处理器
using System.IO; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace WebAPIServerV2 { public class StaticFileHandler : DelegatingHandler { private readonly string _staticRoot; private readonly string _routePrefix = "/images/"; public StaticFileHandler(string staticRoot) { _staticRoot = staticRoot; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var requestPath = request.RequestUri.AbsolutePath; if (requestPath.StartsWith(_routePrefix, System.StringComparison.OrdinalIgnoreCase)) { var filename = requestPath.Substring(_routePrefix.Length); var filePath = Path.Combine(_staticRoot, filename); if (File.Exists(filePath)) { var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(fileStream) }; // 设置Content-Type var ext = Path.GetExtension(filename).ToLowerInvariant(); switch (ext) { case ".jpg": case ".jpeg": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg"); break; case ".png": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png"); break; case ".gif": response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); break; default: response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); break; } return response; } else { return new HttpResponseMessage(HttpStatusCode.NotFound); } } // 非静态资源请求,交给后续处理器处理 return await base.SendAsync(request, cancellationToken); } } }
步骤2:注册处理器到配置
在Start方法中添加自定义处理器:
public void Start(string url) { if (m_Server != null) { Stop(); } var config = new HttpSelfHostConfiguration(url); config.DependencyResolver = new AutofacWebApiDependencyResolver(m_lifetimeScope); config.MaxReceivedMessageSize = int.MaxValue; // 注册静态文件处理器 var imageRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images"); config.MessageHandlers.Add(new StaticFileHandler(imageRoot)); // 原有路由配置 config.Routes.MapHttpRoute( name: "ServerAPI", routeTemplate: "server/{controller}/{action}" ); // 原有格式化配置 config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter()); config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; m_Server = new HttpSelfHostServer(config); m_Server.OpenAsync().Wait(); if (Environment.UserInteractive) Console.WriteLine($"WebAPI server start at:{url}"); }
注意事项
- 此方式无需额外控制器,直接在消息拦截层处理,性能略优
- 同样需确保静态文件目录存在且有读取权限
内容的提问来源于stack exchange,提问作者Izikon
相关产品推荐
相关产品推荐

