public void Start() { var Root = FileNameHandling.GetDirectoryPathWithTailingSeparator(FileNameHandling.GetAbsolutePath(PhysicalPath, Environment.CurrentDirectory)); var Indices = this.Indices; var MimeTypes = new Dictionary <String, String>(StringComparer.OrdinalIgnoreCase); MimeTypes.Add("htm", "text/html"); MimeTypes.Add("html", "text/html"); MimeTypes.Add("shtml", "text/html"); MimeTypes.Add("xml", "text/xml"); MimeTypes.Add("css", "text/css"); MimeTypes.Add("js", "application/x-javascript"); MimeTypes.Add("txt", "text/plain"); MimeTypes.Add("gif", "image/gif"); MimeTypes.Add("jpg", "image/jpeg"); MimeTypes.Add("jpeg", "image/jpeg"); MimeTypes.Add("png", "image/png"); MimeTypes.Add("tif", "image/tiff"); MimeTypes.Add("tiff", "image/tiff"); MimeTypes.Add("ico", "image/x-icon"); MimeTypes.Add("mp3", "audio/mpeg"); MimeTypes.Add("wav", "audio/wav"); MimeTypes.Add("mid", "audio/midi"); MimeTypes.Add("midi", "audio/midi"); Func <String, String> GetMimeType = Extension => { if (MimeTypes.ContainsKey(Extension)) { return(MimeTypes[Extension]); } return("application/octet-stream"); }; Func <String, Int64, Optional <KeyValuePair <Int64, Int64> > > TryGetRange = (RangeStrs, FileLength) => { // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html Int64 Start = 0; Int64 Length = FileLength; var RangeStrsTrimmed = RangeStrs.Trim(' '); if (RangeStrsTrimmed.StartsWith("bytes=")) { RangeStrsTrimmed = RangeStrsTrimmed.Substring("bytes=".Length); } else { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } var RangeStrsSplitted = RangeStrsTrimmed.Split(','); if (RangeStrsSplitted.Length != 1) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } var Parts = RangeStrsSplitted.Single().Trim(' ').Split('-').Select(p => p.Trim(' ')).ToArray(); if (Parts.Length != 2) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } if (Parts[0] == "") { // 不支持suffix-byte-range-spec = "-" suffix-length return(Optional <KeyValuePair <Int64, Int64> > .Empty); } if (!Int64.TryParse(Parts[0], out Start)) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } if ((Start < 0) || (Start > FileLength)) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } if (Parts[1] == "") { Length = FileLength - Start; } else { Int64 End; if (!Int64.TryParse(Parts[1], out End)) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } if (End < Start) { return(Optional <KeyValuePair <Int64, Int64> > .Empty); } Length = Math.Min(End + 1 - Start, FileLength - Start); } return(new KeyValuePair <Int64, Int64>(Start, Length)); }; Action <String, HttpListenerContext, IPEndPoint, Action, Action <Exception> > RequestHandler = (RelativePath, a, e, OnSuccess, OnFailure) => { if (a.Request.ContentLength64 > 0) { a.Response.StatusCode = 400; OnSuccess(); return; } if (RelativePathTranslator != null) { var oRelativePath = RelativePathTranslator(RelativePath); if (oRelativePath.OnNone) { a.Response.StatusCode = 404; OnSuccess(); return; } RelativePath = oRelativePath.Value; } var Path = FileNameHandling.GetAbsolutePath(RelativePath, Root); if ((RelativePath != "") && !Path.StartsWith(Root)) { a.Response.StatusCode = 400; OnSuccess(); return; } if (!File.Exists(Path)) { var Found = false; var UnescapedPath = Uri.UnescapeDataString(Path); if (File.Exists(UnescapedPath)) { Path = UnescapedPath; Found = true; } if (!Found) { foreach (var Index in Indices) { var IndexPath = FileNameHandling.GetPath(Path, Index); if (File.Exists(IndexPath)) { Path = IndexPath; Found = true; break; } } foreach (var Index in Indices) { var IndexPath = FileNameHandling.GetPath(UnescapedPath, Index); if (File.Exists(IndexPath)) { Path = IndexPath; Found = true; break; } } } if (!Found) { a.Response.StatusCode = 404; OnSuccess(); return; } } if (!Path.StartsWith(Root)) { a.Response.StatusCode = 400; OnSuccess(); return; } var Buffer = new Byte[512 * 1024]; using (var fs = Streams.OpenReadable(Path)) { var LastWriteTime = File.GetLastWriteTimeUtc(Path); var LastWriteTimeStr = LastWriteTime.ToString("R"); var ETag = "\"" + Times.DateTimeUtcToString(LastWriteTime) + "\""; var IfModifiedSinceStr = a.Request.Headers["If-Modified-Since"]; if ((IfModifiedSinceStr != null) && (LastWriteTimeStr == IfModifiedSinceStr)) { a.Response.StatusCode = 304; OnSuccess(); return; } var oRange = Optional <KeyValuePair <Int64, Int64> > .Empty; var IfRangeStr = a.Request.Headers["If-Range"]; if ((IfRangeStr == null) || (ETag == IfRangeStr) || (LastWriteTimeStr == IfRangeStr)) { var RangeStrs = a.Request.Headers["Range"]; if (RangeStrs != null) { oRange = TryGetRange(RangeStrs, fs.Length); } } Int64 Start; Int64 Length; if (oRange.OnSome) { var Range = oRange.Value; Start = Range.Key; Length = Range.Value; a.Response.StatusCode = 206; a.Response.Headers.Add("Content-Range", "bytes {0}-{1}/{2}".Formats(Range.Key, Range.Key + Range.Value - 1, fs.Length)); } else { Start = 0; Length = fs.Length; a.Response.StatusCode = 200; } a.Response.ContentLength64 = Length; a.Response.ContentType = GetMimeType(FileNameHandling.GetExtendedFileName(Path)); a.Response.Headers.Add("Accept-Ranges", "bytes"); a.Response.Headers.Add("Last-Modified", LastWriteTimeStr); a.Response.Headers.Add("ETag", ETag); try { using (var ros = a.Response.OutputStream) { var Count = (Length + Buffer.Length - 1) / Buffer.Length; fs.Position = Start; for (int k = 0; k < Count; k += 1) { var ChunkSize = (int)(Math.Min(Buffer.Length, Length - Buffer.Length * k)); fs.Read(Buffer, 0, ChunkSize); ros.Write(Buffer, 0, ChunkSize); } } } catch (System.Net.HttpListenerException) { } } OnSuccess(); }; Inner = new ExternalHttpServer(ServerContext, RequestHandler, QueueUserWorkItem, 8 * 1024); Inner.Bindings = Bindings; Inner.SessionIdleTimeout = SessionIdleTimeout; Inner.MaxConnections = MaxConnections; Inner.MaxConnectionsPerIP = MaxConnectionsPerIP; Inner.MaxBadCommands = MaxBadCommands; Inner.MaxUnauthenticatedPerIP = MaxUnauthenticatedPerIP; Inner.ServiceVirtualPath = ServiceVirtualPath; Inner.Start(); }
public void SaveAll() { lock (SaveLockee) { var InstancesSnapshot = new List <Lazy <InstanceInfo> >(); lock (Instances) { InstancesSnapshot = Instances.Values.ToList(); } foreach (var p in InstancesSnapshot) { var i = p.Value; DateTime Time; Version Version; using (var da = new KrustallosDataAccess(i.Instance, i.Data, IsolationLevel.Snapshot, (ITransactionLock)(null))) { Version = da.GetReaderVersion(); Time = DateTime.UtcNow; var Dir = FileNameHandling.GetFileDirectory(i.FilePath); if (!Directory.Exists(Dir)) { Directory.CreateDirectory(Dir); } using (var s = new ReliableFileWriteStream(i.FilePath)) { da.Save(i.sbs, i.bs, s, i.Schema); } } if (i.BackupDir != "") { if (!Directory.Exists(i.BackupDir)) { Directory.CreateDirectory(i.BackupDir); } var FileName = FileNameHandling.GetFileName(i.FilePath); var FilePath = FileNameHandling.GetPath(i.BackupDir, FileNameHandling.GetMainFileName(FileName) + Time.ToString("yyyyMMddHHmmss", System.Globalization.CultureInfo.InvariantCulture) + "-" + Version.ToString() + "." + FileNameHandling.GetExtendedFileName(FileName)); if (!File.Exists(FilePath)) { File.Copy(i.FilePath, FilePath + ".new", true); File.Move(FilePath + ".new", FilePath); } if (i.MaxBackupCount.OnSome) { var MaxBackupCount = i.MaxBackupCount.Value; var FilesToDelete = new List <String>(); var FilePaths = new SortedSet <String>(StringComparer.OrdinalIgnoreCase); foreach (var f in Directory.EnumerateFiles(i.BackupDir, "*", SearchOption.TopDirectoryOnly)) { FilePaths.Add(f); while (FilePaths.Count > MaxBackupCount) { var First = FilePaths.First(); FilePaths.Remove(First); FilesToDelete.Add(First); } } foreach (var f in FilesToDelete) { if (File.Exists(f)) { try { File.Delete(f); } catch { } } } } } } } }