From 14f8155df63ad2b0616bd556414350081ead6b5f Mon Sep 17 00:00:00 2001 From: Pavel Vesely Date: Sun, 6 Dec 2020 16:09:46 +0100 Subject: [PATCH] FileController fix - using PhysicalFile framework method (current implementation causes file locks and 500 error at heavy load) - Add correct mimetype to header based on file extension --- Oqtane.Server/Controllers/FileController.cs | 33 +++++++------------- Oqtane.Server/Extensions/StringExtensions.cs | 14 +++++++++ 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs index fb43a7cb..5389b423 100644 --- a/Oqtane.Server/Controllers/FileController.cs +++ b/Oqtane.Server/Controllers/FileController.cs @@ -17,6 +17,7 @@ using Oqtane.Enums; using Oqtane.Infrastructure; using Oqtane.Repository; using Microsoft.AspNetCore.Routing.Constraints; +using Oqtane.Extensions; // ReSharper disable StringIndexOfIsCultureSpecific.1 @@ -314,9 +315,9 @@ namespace Oqtane.Controllers { string merged = ""; - // parse the filename which is in the format of filename.ext.part_x_y + // parse the filename which is in the format of filename.ext.part_x_y string token = ".part_"; - string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y" + string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y" int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1)); filename = Path.GetFileNameWithoutExtension(filename); // base filename @@ -435,45 +436,33 @@ namespace Oqtane.Controllers [HttpGet("download/{id}")] public IActionResult Download(int id) { - string errorpath = Path.Combine(GetFolderPath("images"), "error.png"); - Models.File file = _files.GetFile(id); + var file = _files.GetFile(id); if (file != null) { if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions)) { - string filepath = Path.Combine(GetFolderPath(file.Folder), file.Name); + var filepath = Path.Combine(GetFolderPath(file.Folder), file.Name); if (System.IO.File.Exists(filepath)) { - var stream = new FileStream(filepath, FileMode.Open); - return File(stream, "application/octet-stream", file.Name); - } - else - { - _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath); - HttpContext.Response.StatusCode = 404; - if (System.IO.File.Exists(errorpath)) - { - var stream = new FileStream(errorpath, FileMode.Open); - return File(stream, "application/octet-stream", file.Name); - } + return PhysicalFile(filepath, file.Name.GetMimeType(), file.Name); } + + _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath); + HttpContext.Response.StatusCode = 404; } else { _logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id); HttpContext.Response.StatusCode = 401; - var stream = new FileStream(errorpath, FileMode.Open); - return File(stream, "application/octet-stream", file.Name); } } else { _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id); HttpContext.Response.StatusCode = 404; - var stream = new FileStream(errorpath, FileMode.Open); - return File(stream, "application/octet-stream", file.Name); } - return null; + string errorPath = Path.Combine(GetFolderPath("images"), "error.png"); + return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, errorPath.GetMimeType()) : null; } private string GetFolderPath(Folder folder) diff --git a/Oqtane.Server/Extensions/StringExtensions.cs b/Oqtane.Server/Extensions/StringExtensions.cs index 49b3b2cd..a2c7c88b 100644 --- a/Oqtane.Server/Extensions/StringExtensions.cs +++ b/Oqtane.Server/Extensions/StringExtensions.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.StaticFiles; namespace Oqtane.Extensions { @@ -11,7 +12,20 @@ namespace Oqtane.Extensions { return false; } + return list.Any(f => s.StartsWith(f)); } + + public static string GetMimeType(this string fileName) + { + var provider = new FileExtensionContentTypeProvider(); + + if (!provider.TryGetContentType(fileName, out var contentType)) + { + contentType = "application/octet-stream"; + } + + return contentType; + } } }