/// <summary> /// Get a file /// </summary> /// <param name="context">Context used to locate and return files</param> public virtual bool GetFile(FileContext context) { var fullPath = GetFullPath(context.Request.Uri); if (fullPath == null || !File.Exists(fullPath)) return false; var streamPath = fullPath; if (_substituteGzipFiles && context.Request.Headers["Accept-Encoding"] != null && context.Request.Headers["Accept-Encoding"].Contains("gzip")) { var compressedPath = fullPath + ".gz"; if (File.Exists(compressedPath)) { streamPath = compressedPath; context.SetGzipSubstitute(); } } var date = File.GetLastWriteTimeUtc(fullPath); // browser ignores second fractions. date = date.AddTicks(-(date.Ticks % TimeSpan.TicksPerSecond)); if (date <= context.BrowserCacheDate) { context.SetNotModified(fullPath, date); return true; } var stream = new FileStream(streamPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); context.SetFile(fullPath, stream, date); return true; }
/// <summary> /// Loops through all services and returns the first matching file. /// </summary> /// <param name="context">Context used to locate and return files</param> public virtual bool GetFile(FileContext context) { foreach (var fileService in _fileServices) { fileService.GetFile(context); if (context.IsFound) return true; } return false; }
/// <summary> /// Get a file /// </summary> /// <param name="context">Context used to locate and return files</param> public virtual bool GetFile(FileContext context) { var fullPath = GetFullPath(context.Request.Uri); if (fullPath == null || !File.Exists(fullPath)) return false; var date = File.GetLastWriteTimeUtc(fullPath); if (date <= context.BrowserCacheDate) { context.SetNotModified(fullPath, date); return true; } var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); context.SetFile(fullPath, stream, date); return true; }
/// <summary> /// Get a file /// </summary> /// <param name="context">Context used to locate and return files</param> public virtual bool GetFile(FileContext context) { var fullPath = GetFullPath(context.Request.Uri); if (fullPath == null || !File.Exists(fullPath)) return false; var date = File.GetLastWriteTimeUtc(fullPath); // browser ignores second fractions. date = date.AddTicks(-(date.Ticks % TimeSpan.TicksPerSecond)); if (date <= context.BrowserCacheDate) { context.SetNotModified(fullPath, date); return true; } var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); context.SetFile(fullPath, stream, date); return true; }
/// <summary> /// Handle the request. /// </summary> /// <param name="context">HTTP context</param> /// <returns><see cref="ModuleResult.Stop"/> will stop all processing except <see cref="IHttpModule.EndRequest"/>.</returns> /// <remarks>Invoked in turn for all modules unless you return <see cref="ModuleResult.Stop"/>.</remarks> public ModuleResult HandleRequest(IHttpContext context) { // only handle GET and HEAD if (!context.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) && !context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase)) return ModuleResult.Continue; // serve a directory if (AllowFileListing) { if (TryGenerateDirectoryPage(context)) return ModuleResult.Stop; } var header = context.Request.Headers["If-Modified-Since"]; var time = header != null ? DateTime.ParseExact(header, "R", CultureInfo.InvariantCulture) : DateTime.MinValue; var fileContext = new FileContext(context.Request, time); _fileService.GetFile(fileContext); if (!fileContext.IsFound) return ModuleResult.Continue; if (!fileContext.IsModified) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.ReasonPhrase = "Was last modified " + fileContext.LastModifiedAtUtc.ToString("R"); return ModuleResult.Stop; } if (fileContext.IsGzipSubstitute) { context.Response.AddHeader("Content-Encoding", "gzip"); } var mimeType = MimeTypeProvider.Instance.Get(fileContext.Filename); if (mimeType == null) { context.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; context.Response.ReasonPhrase = string.Format("File type '{0}' is not supported.", Path.GetExtension(fileContext.Filename)); return ModuleResult.Stop; } context.Response.AddHeader("Last-Modified", fileContext.LastModifiedAtUtc.ToString("R")); context.Response.AddHeader("Accept-Ranges", "bytes"); context.Response.AddHeader("Content-Disposition", "inline;filename=\"" + Path.GetFileName(fileContext.Filename) + "\""); context.Response.ContentType = mimeType; context.Response.ContentLength = (int)fileContext.FileStream.Length; // ranged/partial transfers var rangeStr = context.Request.Headers["Range"]; if (!string.IsNullOrEmpty(rangeStr)) { var ranges = new RangeCollection(); ranges.Parse(rangeStr, (int)fileContext.FileStream.Length); context.Response.AddHeader("Content-Range", ranges.ToHtmlHeaderValue((int)fileContext.FileStream.Length)); context.Response.Body = new ByteRangeStream(ranges, fileContext.FileStream); context.Response.ContentLength = ranges.TotalLength; context.Response.StatusCode = 206; } else context.Response.Body = fileContext.FileStream; // do not include a body when the client only want's to get content information. if (context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase) && context.Response.Body != null) { context.Response.Body.Dispose(); context.Response.Body = null; } return ModuleResult.Stop; }
/// <summary> /// Handle the request. /// </summary> /// <param name="context">HTTP context</param> /// <returns><see cref="ModuleResult.Stop"/> will stop all processing except <see cref="IHttpModule.EndRequest"/>.</returns> /// <remarks>Invoked in turn for all modules unless you return <see cref="ModuleResult.Stop"/>.</remarks> public ModuleResult HandleRequest(IHttpContext context) { // only handle GET and HEAD if (!context.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) && !context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase)) { return(ModuleResult.Continue); } // serve a directory if (AllowFileListing) { if (TryGenerateDirectoryPage(context)) { return(ModuleResult.Stop); } } var header = context.Request.Headers["If-Modified-Since"]; var time = header != null ? DateTime.ParseExact(header, "R", CultureInfo.InvariantCulture) : DateTime.MinValue; var fileContext = new FileContext(context.Request, time); _fileService.GetFile(fileContext); if (!fileContext.IsFound) { return(ModuleResult.Continue); } if (!fileContext.IsModified) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.ReasonPhrase = "Was last modified " + fileContext.LastModifiedAtUtc.ToString("R"); return(ModuleResult.Stop); } if (fileContext.IsGzipSubstitute) { context.Response.AddHeader("Content-Encoding", "gzip"); } var mimeType = MimeTypeProvider.Instance.Get(fileContext.Filename); if (mimeType == null) { context.Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; context.Response.ReasonPhrase = string.Format("File type '{0}' is not supported.", Path.GetExtension(fileContext.Filename)); return(ModuleResult.Stop); } context.Response.AddHeader("Last-Modified", fileContext.LastModifiedAtUtc.ToString("R")); context.Response.AddHeader("Accept-Ranges", "bytes"); context.Response.AddHeader("Content-Disposition", "inline;filename=\"" + Path.GetFileName(fileContext.Filename) + "\""); context.Response.ContentType = mimeType; context.Response.ContentLength = (int)fileContext.FileStream.Length; // ranged/partial transfers var rangeStr = context.Request.Headers["Range"]; if (rangeStr != null && rangeStr.Equals("bytes=0-", StringComparison.OrdinalIgnoreCase)) { rangeStr = ""; //do not create range if everything is wanted. } if (!string.IsNullOrEmpty(rangeStr)) { var ranges = new RangeCollection(); ranges.Parse(rangeStr, (int)fileContext.FileStream.Length); context.Response.AddHeader("Content-Range", ranges.ToHtmlHeaderValue((int)fileContext.FileStream.Length)); context.Response.Body = new ByteRangeStream(ranges, fileContext.FileStream); context.Response.ContentLength = ranges.TotalLength; context.Response.StatusCode = 206; } else { context.Response.Body = fileContext.FileStream; } // do not include a body when the client only want's to get content information. if (context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase) && context.Response.Body != null) { context.Response.Body.Dispose(); context.Response.Body = null; } return(ModuleResult.Stop); }