Web项目开发的过程中,一般会经过设计,切图静态化,程序。
设计工作是很独立的,与其他两个过程没什么关系。
但静态化和程序有时候就需要协作了,在我的实际工作中就遇到这样一个问题:前端在HTML页面里引用的资源路径都是相对的,在本地打开是没问题的,但交给程序后,在web服务器上访问时,往往需要修改这些路径,包括图片引用、样式引用、javascript引用、其他页面的连接等等,就算能批量替换也是很枯燥,而且如果前端又做了修改,这个替换还得做一遍。
所以,如果前端静态化的时候直接用像web服务器上的相对路径就可以解决这个问题了。
开始想的是让前端架设IIS,这样虽然可行,但是不同的项目还要指定不同的目录,前端操作比较复杂,于是就自己写了一个简单的静态文件服务器,只需将一个exe文件和一个配置文件复制到要浏览的目录就行了。
源码:http://git.oschina.net/loogn/StaticFilesServer
特点:
- 基于.net3.5
- 可自定义端口
- 可扩展Mime类型
- 可浏览目录
代码其实是很简单,就是用httpListenner处理GET请求,有注释,不再说明:
class Program
{
//根目录
static string RootPath = System.Environment.CurrentDirectory;
//端口
static string Port = GetSetting("port") ?? "80";
//Mime类型映射
static Dictionary<string, string> MimeMaps = new Dictionary<string, string>();
[STAThread]
static void Main(string[] args)
{
try
{
//加载MimeMap;
LoadMimeMaps();
var url = "http://localhost:" + Port + "/";
var httpListenner = new HttpListener();
httpListenner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
httpListenner.Prefixes.Add(url);
httpListenner.Start();
Console.WriteLine("服务已启动:{0}", url);
//打开浏览器
System.Diagnostics.Process.Start(url);
new Thread(new ThreadStart(delegate
{
try
{
LoopHandle(httpListenner);
}
catch (Exception exp)
{
Console.WriteLine(exp);
}
})).Start();
}
catch (Exception exp)
{
Console.WriteLine(exp);
}
}
/// <summary>
/// 循环处理请求
/// </summary>
/// <param name="httpListenner"></param>
private static void LoopHandle(HttpListener httpListenner)
{
while (true)
{
HttpListenerContext context = httpListenner.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
var file = request.Url.LocalPath.Replace('/', '\\');
var path = RootPath + file;
response.ContentEncoding = Encoding.UTF8;
if (File.Exists(path))
{
HandleFile(response, path);
}
else if (Directory.Exists(path))
{
HandleDirectory(request, response, path);
}
else
{
HandleNotFound(response, path);
}
response.Close();
}
}
/// <summary>
/// 处理文件请求
/// </summary>
/// <param name="response"></param>
/// <param name="path"></param>
private static void HandleFile(HttpListenerResponse response, string path)
{
response.ContentType = GetContentType(path);
var buffer = File.ReadAllBytes(path);
response.OutputStream.Write(buffer, 0, buffer.Length);
}
/// <summary>
/// 处理文件夹请求
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="path"></param>
private static void HandleDirectory(HttpListenerRequest request, HttpListenerResponse response, string path)
{
StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.Append("<head>");
sb.Append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>");
sb.Append("<title>dir</title>");
sb.Append("</head>");
sb.Append("<body>");
sb.Append("<ul>");
var dirList = Directory.GetDirectories(path);
foreach (var dir in dirList)
{
var vdir = Path.GetFileName(dir);
sb.AppendFormat("<li><a href='{0}'><b>{1}</b></a></li>", Path.Combine(request.Url.LocalPath, vdir), vdir);
}
var fileList = Directory.GetFiles(path);
foreach (var f in fileList)
{
var vf = Path.GetFileName(f);
if (!vf.StartsWith("StaticFilesServer.exe"))
{
sb.AppendFormat("<li><a href='{0}'>{1}</a></li>", Path.Combine(request.Url.LocalPath, vf), vf);
}
}
sb.Append("</ul>");
sb.Append("</body>");
sb.Append("</html>");
response.ContentType = "text/html";
var buffer = Encoding.UTF8.GetBytes(sb.ToString());
response.OutputStream.Write(buffer, 0, buffer.Length);
}
/// <summary>
/// 处理404
/// </summary>
/// <param name="response"></param>
/// <param name="path"></param>
private static void HandleNotFound(HttpListenerResponse response, string path)
{
StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.Append("<head>");
sb.Append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>");
sb.Append("<title>404</title>");
sb.Append("</head>");
sb.Append("<body>");
sb.AppendFormat("<h3>没有找到文件:{0}</h3>", path);
sb.Append("</body>");
sb.Append("</html>");
response.ContentType = "text/html";
var buffer = Encoding.UTF8.GetBytes(sb.ToString());
response.OutputStream.Write(buffer, 0, buffer.Length);
}
/// <summary>
/// 得到请求内容的ContentType
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private static string GetContentType(string path)
{
var ext = Path.GetExtension(path).ToLower();
string mime;
if (MimeMaps.TryGetValue(ext, out mime))
{
return mime;
}
else
{
return "";
}
}
/// <summary>
/// 加载MimeMaps
/// </summary>
private static void LoadMimeMaps()
{
var value = GetSetting("mimeMaps");
var lines = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var one = line.Replace(" ", "").Replace(" ", "").ToLower();
if (one.Length > 0)
{
var part = one.Split(new string[] { "=>" }, StringSplitOptions.RemoveEmptyEntries);
MimeMaps[part[0]] = part[1];
}
}
}
private static string GetSetting(string key)
{
var value = System.Configuration.ConfigurationManager.AppSettings.Get(key);
return value;
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<clear/>
<add key="port" value="8088"/>
<add key="mimeMaps" value="
.html => text/html
.htm => text/html
.css => text/css
.js => text/javascript
.gif => image/gif
.png => image/png
.jpg => image/jpeg
.jpeg => image/jpeg
.ico => image/x-icon
.woff => application/x-font-woff
"/>
</appSettings>
</configuration>
测试文件夹结构:
web\
web\index.html
web\StaticFilesServer.exe
web\StaticFilesServer.exe.config
web\content\
web\content\image.png
web\content\style.css
双击StaticFilesServer.exe会启动服务,并会在默认浏览器中打开web根目录: