public override async Task <Stream> Handle(HttpRequest request, HttpResponse response) { Log.LogDebug("HandleStream get file"); string file = string.Empty; if (request.Query.ContainsKey(string.Empty)) { file = request.Query[string.Empty][0]; file = HttpUtility.UrlDecode(file); } if (ProgramSettings.Settings.Dlna && !string.IsNullOrEmpty(file)) { try { var fileRequest = await FileRequest.Create(request, file); if (fileRequest.File.Exists && Tools.Tools.CheckAccessPath(fileRequest.File.FullName)) { response.Headers.Add("Accept-Ranges", "bytes"); if (ValidateRanges(response, fileRequest) && ValidateModificationDate(request, response, fileRequest) && ValidateEntityTag(request, response, fileRequest)) { response.Headers.Add("Last-Modified", fileRequest.File.LastWriteTime.ToString("r")); response.Headers["Etag"] = fileRequest.EntityTag; if (!fileRequest.RangeRequest) { response.ContentLength = fileRequest.File.Length; response.ContentType = fileRequest.ContentType; response.StatusCode = (int)HttpStatusCode.OK; var fileStream = fileRequest.File.OpenRead(); fileStream.Position = 0; return(fileStream); } else { response.ContentLength = fileRequest.GetContentLength(); if (!fileRequest.MultipartRequest) { response.Headers.Add("Content-Range", $"bytes {fileRequest.RangesStartIndexes[0]}-{fileRequest.RangesEndIndexes[0]}/{fileRequest.File.Length}"); response.ContentType = fileRequest.ContentType; } else { response.ContentType = $"multipart/byteranges; boundary={fileRequest.Boundary}"; } response.StatusCode = (int)HttpStatusCode.PartialContent; var fileStream = fileRequest.File.OpenRead(); fileStream.Position = fileRequest.RangesStartIndexes[0]; return(fileStream); } } } else { Log.LogDebug("File not found: {0}", file); response.StatusCode = (int)HttpStatusCode.NotFound; } } catch (Exception exception) { Log.LogError(exception); response.StatusCode = (int)HttpStatusCode.NotFound; } } else { Log.LogDebug("Incorrect parameter: {0}", file); response.StatusCode = (int)HttpStatusCode.NoContent; } return(null); }
private static bool ValidateEntityTag(HttpRequest request, HttpResponse response, FileRequest fileRequest) { if (request.Headers.ContainsKey("If-Match")) { string matchHeader = request.Headers["If-Match"]; if (matchHeader != "*") { var entitiesTags = matchHeader.Split(FileRequest.CommaSplitArray); int entitieTagIndex = 0; for (; entitieTagIndex < entitiesTags.Length; entitieTagIndex++) { if (fileRequest.EntityTag == entitiesTags[entitieTagIndex]) { break; } } if (entitieTagIndex >= entitiesTags.Length) { response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } } if (request.Headers.ContainsKey("If-None-Match")) { string noneMatchHeader = request.Headers["If-None-Match"]; if (!string.IsNullOrEmpty(noneMatchHeader)) { if (noneMatchHeader == "*") { response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } var entitiesTags = noneMatchHeader.Split(FileRequest.CommaSplitArray); if (entitiesTags.All(entityTag => fileRequest.EntityTag == entityTag)) { response.Headers["Etag"] = fileRequest.EntityTag; response.StatusCode = (int)HttpStatusCode.NotModified; return(false); } } } return(true); }