在独立模式下使用ServiceStack,我在Apphost中为任意文件名定义了一个catch-all处理程序(它只提供数据目录中的文件)。
其核心方法是(fi
是FileInfo
成员变量,ExtensionContentType
是Dictionary
从MIME类型的扩展名:)
public class StaticFileHandler : EndpointHandlerBase
{
protected static readonly Dictionary<string, string> ExtensionContentType;
protected FileInfo fi;
static StaticFileHandler()
{
ExtensionContentType = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{ ".text", "text/plain" },
{ ".js", "text/javascript" },
{ ".css", "text/css" },
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".png", "image/png" },
{ ".ico", "image/x-icon" },
{ ".gif", "image/gif" },
{ ".bmp", "image/bmp" },
{ ".jpg", "image/jpeg" }
};
}
public string BaseDirectory { protected set; get; }
public string Prefix { protected set; get; }
public StaticFileHandler(string baseDirectory, string prefix)
{
BaseDirectory = baseDirectory;
Prefix = prefix;
}
private StaticFileHandler(FileInfo fi)
{
this.fi = fi;
}
public static StaticFileHandler Factory(string baseDirectory, string prefix, string pathInfo)
{
if (!pathInfo.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
{
return null;
}
var fn = baseDirectory + "/" + pathInfo.After(prefix.Length);
Console.Write("StaticFileHandler.Factory fn=" + fn);
Console.WriteLine("AbsoluteUri={0}", pathInfo);
var fi = new System.IO.FileInfo(fn);
if (!fi.Exists)
{
return null;
}
return new StaticFileHandler(fi);
}
public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
{
using (var source = new System.IO.FileStream(fi.FullName, System.IO.FileMode.Open))
{
source.CopyTo(httpRes.OutputStream);
//var bytes = source.ReadAllBytes();
//httpRes.OutputStream.Write(bytes, 0, bytes.Length);
}
// timeStamp = fi.LastWriteTime;
httpRes.AddHeader("Date", DateTime.Now.ToString("R"));
httpRes.AddHeader("Content-Type", ExtensionContentType.Safeget(fi.Extension) ?? "text/plain");
//httpRes.ContentType = ExtensionContentType.Safeget(fi.Extension, "text/plain");
}
public override object CreateRequest(IHttpRequest request, string operationName)
{
return null;
}
public override object GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, object request)
{
return null;
}
}
当我使用标记为方法1的方法或方法2处于活动状态运行时,未设置实际的HTTP响应类型标头。使用IE9开发人员工具进行调试表明根本没有设置响应类型。
从catch-all处理程序设置内容类型(和流内容)的正确方法是什么?
这不是标准服务,所以我不能只返回一个自定义的IHttpResponse
,这似乎是正常的服务方法。
附加信息:日期标题也未设置...
答案 0 :(得分:2)
我认为问题在于此行source.CopyTo(httpRes.OutputStream);
如果您执行类似
的操作,则应填充标题public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
{
var bytes = File.ReadAllBytes(fi.FullName);
httpRes.AddHeader("Date", DateTime.Now.ToString("R"));
httpRes.AddHeader("Content-Type", "text/plain");
httpRes.AddHeader("TestHeader", "SomeValue");
httpRes.OutputStream.Write(bytes, 0, bytes.Length);
}
用于测试答案的简单控制台应用
初始化ServiceStack AppHost并在控制台中运行:
class Program
{
static void Main(string[] args)
{
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:1337/");
System.Console.WriteLine("Listening on http://localhost:1337/ ...");
System.Console.ReadLine();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
一些虚拟服务......对于这个答案来说并不是必需的:
[Route("/Hello/{Name}")]
public class Hello
{
public string Name { get; set; }
}
public class HelloService : Service
{
public string Any(Hello request)
{
return request.Name;
}
}
配置AppHost并将“测试中的代码”添加到CatchAllHanders:
public class AppHost : AppHostHttpListenerBase
{
public AppHost() : base("Test Console", typeof(AppHost).Assembly) { }
public override void Configure(Funq.Container container)
{
CatchAllHandlers.Add(StaticFileHandler.Factory);
}
}
修改后的'测试中的代码' - 主要需要获取ProcessRequest()并返回一个文件:
public class StaticFileHandler : EndpointHandlerBase
{
protected static readonly Dictionary<string, string> ExtensionContentType;
protected FileInfo fi;
static StaticFileHandler()
{
ExtensionContentType = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{ ".text", "text/plain" },
{ ".js", "text/javascript" },
{ ".css", "text/css" },
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".png", "image/png" },
{ ".ico", "image/x-icon" },
{ ".gif", "image/gif" },
{ ".bmp", "image/bmp" },
{ ".jpg", "image/jpeg" }
};
}
public string BaseDirectory { protected set; get; }
public string Prefix { protected set; get; }
public StaticFileHandler(string baseDirectory, string prefix)
{
BaseDirectory = baseDirectory;
Prefix = prefix;
}
private StaticFileHandler(FileInfo fi)
{
this.fi = fi;
}
public static StaticFileHandler Factory(string baseDirectory, string prefix, string pathInfo)
{
return new StaticFileHandler(new FileInfo(@"C:\Test.xml"));
}
public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
{
var bytes = File.ReadAllBytes(fi.FullName);
httpRes.AddHeader("Date", DateTime.Now.ToString("R"));
httpRes.AddHeader("Content-Type", "text/plain");
httpRes.AddHeader("Test", "SetThis");
httpRes.OutputStream.Write(bytes, 0, bytes.Length);
}
public override object CreateRequest(IHttpRequest request, string operationName)
{
return null;
}
public override object GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, object request)
{
return null;
}
}