commit
05b0b74578
@ -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 = "")
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
31
Oqtane.Server/Extensions/MimeUtilities.cs
Normal file
31
Oqtane.Server/Extensions/MimeUtilities.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
@ -19,16 +18,14 @@ namespace Oqtane.Infrastructure
|
|||||||
private readonly IConfigurationRoot _config;
|
private readonly IConfigurationRoot _config;
|
||||||
private readonly IUserPermissions _userPermissions;
|
private readonly IUserPermissions _userPermissions;
|
||||||
private readonly IHttpContextAccessor _accessor;
|
private readonly IHttpContextAccessor _accessor;
|
||||||
private readonly IStringLocalizer _localizer;
|
|
||||||
|
|
||||||
public LogManager(ILogRepository logs, ITenantResolver tenantResolver, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor, IStringLocalizer<LogManager> localizer)
|
public LogManager(ILogRepository logs, ITenantResolver tenantResolver, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
|
||||||
{
|
{
|
||||||
_logs = logs;
|
_logs = logs;
|
||||||
_tenantResolver = tenantResolver;
|
_tenantResolver = tenantResolver;
|
||||||
_config = config;
|
_config = config;
|
||||||
_userPermissions = userPermissions;
|
_userPermissions = userPermissions;
|
||||||
_accessor = accessor;
|
_accessor = accessor;
|
||||||
_localizer = localizer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(LogLevel level, object @class, LogFunction function, string message, params object[] args)
|
public void Log(LogLevel level, object @class, LogFunction function, string message, params object[] args)
|
||||||
@ -124,7 +121,6 @@ namespace Oqtane.Infrastructure
|
|||||||
log.LogDate = DateTime.UtcNow;
|
log.LogDate = DateTime.UtcNow;
|
||||||
log.Server = Environment.MachineName;
|
log.Server = Environment.MachineName;
|
||||||
log.MessageTemplate = log.Message;
|
log.MessageTemplate = log.Message;
|
||||||
log.Message = _localizer[log.Message];
|
|
||||||
log = ProcessStructuredLog(log);
|
log = ProcessStructuredLog(log);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
@ -380,4 +386,4 @@ namespace Oqtane.Shared
|
|||||||
return dictionary;
|
return dictionary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ V.1.0.0 ( released in conjunction with .NET Core 3.2 on May 19, 2020 )
|
|||||||
- [x] Dynamic CSS/Lazy Loading
|
- [x] Dynamic CSS/Lazy Loading
|
||||||
|
|
||||||
Future Consideration
|
Future Consideration
|
||||||
- [ ] OAuth Support
|
- [ ] Support For Additional Authentication Providers (ie. OAuth)
|
||||||
- [ ] Site Configuration Migrations
|
- [ ] Site Configuration Migrations
|
||||||
- [ ] Pub/Sub Event Framework
|
- [ ] Pub/Sub Event Framework
|
||||||
- [ ] Admin UI Markup Optimization ( ie. replace tables with divs in forms )
|
- [ ] Admin UI Markup Optimization ( ie. replace tables with divs in forms )
|
||||||
|
Reference in New Issue
Block a user