Following my post on mini-web server with WCF, I've been asked about how to serve static files (images, stylesheets, scripts).
WCF services can return a Stream, so it's just a matter of calling File.OpenRead to get a the stream
public Stream GetFile(string file) {
// We forbid access to directories outside of the site root
if (file.Contains("..")) throw new SecurityException(); var ext = Path.GetExtension(file).ToLower().TrimStart('.');
// Just a helper that will
// set WebOperationContext.Current.OutgoingResponse.ContentType
SetContentType(ContentInfo.For(ext)); var filePath = Path.Combine(this.siteRoot, file); return File.OpenRead(GetActualFilePath(filePath)); }
ContentInfo.For() is a helper for mapping an extension to a mimetype, with a two-stage lookup:
/// <summary> /// Represents info on a given file /// </summary> public static class ContentInfo { static readonly KeyValuePair<MimeTypes, string>[] contentInfoFor = new[] { new KeyValuePair<MimeTypes, string>(MimeTypes.Js, "text/javascript"), new KeyValuePair<MimeTypes, string>(MimeTypes.Css, "text/css"), new KeyValuePair<MimeTypes, string>(MimeTypes.Html, "text/html"), new KeyValuePair<MimeTypes, string>(MimeTypes.Plain, "text/plain"), new KeyValuePair<MimeTypes, string>(MimeTypes.Gif, "image/gif"), new KeyValuePair<MimeTypes, string>(MimeTypes.Jpeg, "image/jpeg"), new KeyValuePair<MimeTypes, string>(MimeTypes.Tiff, "image/tiff"), }; /// <summary> /// Gets the mime type for a given <see cref="MimeTypes"/> /// </summary> /// <param name="mimeType">The file's <see cref="MimeTypes"/></param> /// <returns>The file's mime type</returns> public static string For(MimeTypes mimeType) { return (from p in contentInfoFor where p.Key == mimeType select p.Value) .First(); } /// <summary> /// Gets the mime type for a given extension /// </summary> /// <param name="extension">The file's extension</param> /// <returns>The file's mime type</returns> public static string For(string extension) { return For(MimeType.For(extension)); } }
and
/// <summary> /// Helpers for <see cref="MimeTypes"/> /// </summary> public class MimeType { static readonly KeyValuePair<string, MimeTypes>[] mimeTypeForExtension = new[] { new KeyValuePair<string, MimeTypes>("js", MimeTypes.Js), new KeyValuePair<string, MimeTypes>("css", MimeTypes.Css), new KeyValuePair<string, MimeTypes>("htm", MimeTypes.Html), new KeyValuePair<string, MimeTypes>("html", MimeTypes.Html), new KeyValuePair<string, MimeTypes>("txt", MimeTypes.Plain), new KeyValuePair<string, MimeTypes>("gif", MimeTypes.Gif), new KeyValuePair<string, MimeTypes>("jpg", MimeTypes.Jpeg), new KeyValuePair<string, MimeTypes>("jpeg", MimeTypes.Jpeg), new KeyValuePair<string, MimeTypes>("tiff", MimeTypes.Tiff), }; /// <summary> /// Selects a <see cref="MimeTypes"/> for a given file extension /// </summary> /// <param name="extension">The file's extension</param> /// <returns>The file's mime type</returns> public static MimeTypes For(string extension) { extension = extension.TrimStart('.'); return (from p in mimeTypeForExtension where p.Key == extension select p.Value) .First(); } }
When MimeTypes are:
public enum MimeTypes { Js, Css, Html, Gif, Jpeg, Tiff, Plain }