/// <summary> /// Get a file for a request. If the /// </summary> /// <param name="request">The request.</param> /// <param name="imageIdRef">The image identifier reference.</param> /// <param name="generateEtagFn">The generate e-tag function.</param> /// <returns> /// The file response or a NotModified response if the e-tag matches. /// </returns> public static HttpResponseMessage GetFileForRequest(HttpRequestMessage request, ERM.EntityRef imageIdRef, Func <ERM.EntityRef, string> generateEtagFn) { string etag = generateEtagFn(imageIdRef); // If the request contains the same e-tag then return a not modified if (request.Headers.IfNoneMatch != null && request.Headers.IfNoneMatch.Any(et => et.Tag == etag)) { var notModifiedResponse = new HttpResponseMessage(HttpStatusCode.NotModified); notModifiedResponse.Headers.ETag = new EntityTagHeaderValue(etag, false); return(notModifiedResponse); } // Return the image var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(FileRepositoryHelper.GetFileDataStreamForEntity(imageIdRef)) }; response.Headers.ETag = new EntityTagHeaderValue(etag, false); response.Headers.CacheControl = new CacheControlHeaderValue { MustRevalidate = true, MaxAge = new TimeSpan(0) }; // Yuck. You gotta do what you gotta do. bool isIosDevice = false; if (request.Headers.UserAgent != null) { isIosDevice = request.Headers.UserAgent.Any(ua => IosMobileRegex.IsMatch(ua.ToString())); } string contentType = string.Empty; // Note: We are not setting the content length because the CompressionHandler will compress the stream. // Specifying the length here will cause the browser to hang as the actual data it // receives (as it is compressed) will be less than the specified content length. FileDetails dbFileType = FileRepositoryHelper.GetStreamContentType(imageIdRef); if (dbFileType != null) { response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = dbFileType.Filename }; // Found that specifying specific mime types on IOS mobile // causes safari to raise errors. // However, found that on Android the download // manager requires the mime type so that the downloaded // file can be opened by tapping. if (!isIosDevice) { if (!string.IsNullOrWhiteSpace(dbFileType.ContentType)) { contentType = dbFileType.ContentType; } else { // Attempt to get a mime type from the file name if (!string.IsNullOrWhiteSpace(dbFileType.Filename)) { contentType = MimeMapping.GetMimeMapping(dbFileType.Filename); } } } } // If we don't have a content type, fallback to the generic one. if (string.IsNullOrWhiteSpace(contentType)) { contentType = "application/octet-stream"; } response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType); return(response); }