FileController - content disposition

This commit is contained in:
Pavel Vesely 2020-12-15 10:49:48 +01:00
parent deaaa74fc8
commit 07711c082e
5 changed files with 93 additions and 27 deletions

View File

@ -116,7 +116,12 @@ namespace Oqtane.Modules
public string ContentUrl(int fileid) public string ContentUrl(int fileid)
{ {
return Utilities.ContentUrl(PageState.Alias, fileid); return ContentUrl(fileid, false);
}
public string ContentUrl(int fileid, bool asAttachment)
{
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
} }
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "") public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")

View File

@ -66,7 +66,7 @@ namespace Oqtane.Controllers
{ {
foreach (string file in Directory.GetFiles(folder)) foreach (string file in Directory.GetFiles(folder))
{ {
files.Add(new Models.File { Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "") }); files.Add(new Models.File {Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "")});
} }
} }
} }
@ -147,8 +147,10 @@ namespace Oqtane.Controllers
{ {
Directory.CreateDirectory(folderpath); Directory.CreateDirectory(folderpath);
} }
System.IO.File.Move(Path.Combine(GetFolderPath(_file.Folder), _file.Name), Path.Combine(folderpath, file.Name)); System.IO.File.Move(Path.Combine(GetFolderPath(_file.Folder), _file.Name), Path.Combine(folderpath, file.Name));
} }
file.Extension = Path.GetExtension(file.Name).ToLower().Replace(".", ""); file.Extension = Path.GetExtension(file.Name).ToLower().Replace(".", "");
file = _files.UpdateFile(file); file = _files.UpdateFile(file);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file); _logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file);
@ -221,7 +223,7 @@ namespace Oqtane.Controllers
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Create, _logger.Log(LogLevel.Error, this, LogFunction.Create,
"File Could Not Be Downloaded From Url Due To Its File Extension {Url}", url); "File Could Not Be Downloaded From Url Due To Its File Extension {Url}", url);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict;
return file; return file;
} }
@ -229,7 +231,7 @@ namespace Oqtane.Controllers
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Create, _logger.Log(LogLevel.Error, this, LogFunction.Create,
$"File Could Not Be Downloaded From Url Due To Its File Name Not Allowed {url}"); $"File Could Not Be Downloaded From Url Due To Its File Name Not Allowed {url}");
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict;
return file; return file;
} }
@ -266,7 +268,7 @@ namespace Oqtane.Controllers
if (!file.FileName.IsPathOrFileValid()) if (!file.FileName.IsPathOrFileValid())
{ {
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict;
return; return;
} }
@ -432,9 +434,38 @@ namespace Oqtane.Controllers
return canaccess; return canaccess;
} }
/// <summary>
/// Get file with header
/// Content-Disposition: inline
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
/// </summary>
/// <param name="id">File Id from Oqtane filesystem </param>
/// <returns>file content</returns>
// GET api/<controller>/download/5 // GET api/<controller>/download/5
[HttpGet("download/{id}")] [HttpGet("download/{id}")]
public IActionResult Download(int id) public IActionResult DownloadInline(int id)
{
return Download(id, false);
}
/// <summary>
/// Get file with header
/// Content-Disposition: attachment; filename="filename.jpg"
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
///
/// </summary>
/// <param name="id">File Id from Oqtane filesystem</param>
/// <returns></returns>
// GET api/<controller>/download/5/attach
[HttpGet("download/{id}/attach")]
public IActionResult DownloadAttachment(int id)
{
return Download(id, true);
}
private IActionResult Download(int id, bool asAttachment)
{ {
var file = _files.GetFile(id); var file = _files.GetFile(id);
if (file != null) if (file != null)
@ -444,7 +475,10 @@ namespace Oqtane.Controllers
var filepath = Path.Combine(GetFolderPath(file.Folder), file.Name); var filepath = Path.Combine(GetFolderPath(file.Folder), file.Name);
if (System.IO.File.Exists(filepath)) if (System.IO.File.Exists(filepath))
{ {
return PhysicalFile(filepath, file.Name.GetMimeType(), file.Name); var result = asAttachment
? PhysicalFile(filepath, file.GetMimeType(), file.Name)
: PhysicalFile(filepath, file.GetMimeType());
return result;
} }
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath); _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
@ -461,8 +495,9 @@ namespace Oqtane.Controllers
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id); _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
HttpContext.Response.StatusCode = 404; HttpContext.Response.StatusCode = 404;
} }
string errorPath = Path.Combine(GetFolderPath("images"), "error.png"); string errorPath = Path.Combine(GetFolderPath("images"), "error.png");
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, errorPath.GetMimeType()) : null; return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
} }
private string GetFolderPath(Folder folder) private string GetFolderPath(Folder folder)
@ -480,7 +515,7 @@ namespace Oqtane.Controllers
if (!Directory.Exists(folderpath)) if (!Directory.Exists(folderpath))
{ {
string path = ""; string path = "";
var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; var separators = new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries); string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (string folder in folders) foreach (string folder in folders)
{ {
@ -501,7 +536,7 @@ namespace Oqtane.Controllers
FileInfo fileinfo = new FileInfo(filepath); FileInfo fileinfo = new FileInfo(filepath);
file.Extension = fileinfo.Extension.ToLower().Replace(".", ""); file.Extension = fileinfo.Extension.ToLower().Replace(".", "");
file.Size = (int)fileinfo.Length; file.Size = (int) fileinfo.Length;
file.ImageHeight = 0; file.ImageHeight = 0;
file.ImageWidth = 0; file.ImageWidth = 0;

View File

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.StaticFiles;
using Oqtane.Models;
namespace Oqtane.Extensions
{
public static class MimeUtilities
{
/// <summary>
/// Return Mime content type based on file extension
/// </summary>
/// <param name="fileName">File name</param>
public static string GetMimeType(string fileName)
{
var provider = new FileExtensionContentTypeProvider();
if (!provider.TryGetContentType(fileName, out var contentType))
contentType = "application/octet-stream";
// we can add additional mappings here
return contentType;
}
/// <summary>
/// Return Mime content type based on file extension
/// </summary>
public static string GetMimeType(this File file)
{
return GetMimeType(file?.Name);
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Oqtane.Models;
namespace Oqtane.Extensions namespace Oqtane.Extensions
{ {
@ -15,17 +16,5 @@ namespace Oqtane.Extensions
return list.Any(f => s.StartsWith(f)); 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;
}
} }
} }

View File

@ -95,11 +95,17 @@ namespace Oqtane.Shared
return NavigateUrl(alias, path, parameters); return NavigateUrl(alias, path, parameters);
} }
public static string ContentUrl(Alias alias, int fileid) public static string ContentUrl(Alias alias, int fileId)
{ {
string url = (alias == null) ? "/~" : "/" + alias.AliasId; return ContentUrl(alias, fileId, false);
url += Constants.ContentUrl + fileid.ToString(); }
return url;
public static string ContentUrl(Alias alias, int fileId, bool asAttachment)
{
var aliasUrl = (alias == null) ? "/~" : "/" + alias.AliasId;
var method = asAttachment ? "/attach":"";
return $"{aliasUrl}{Constants.ContentUrl}{fileId}{method}";
} }
public static string GetTypeName(string fullyqualifiedtypename) public static string GetTypeName(string fullyqualifiedtypename)