281 lines
12 KiB
C#
281 lines
12 KiB
C#
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Core.Interfaces;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.StaticFiles;
|
|
using Microsoft.Extensions.Primitives;
|
|
|
|
namespace gehGassi.Web.Controllers
|
|
{
|
|
/// <summary>
|
|
/// Controller für die Rückgabe von Dateien, Bilder usw.
|
|
/// </summary>
|
|
[Route("File")]
|
|
public class FileController : Controller
|
|
{
|
|
private readonly IFileService _fileService;
|
|
private readonly IFileShareService _fileShareService;
|
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="fileService">Instanz eines IFileService</param>
|
|
/// <param name="fileShareService">Instnanz eines IFileShareService</param>
|
|
/// <param name="webHostEnvironment">Instanz eines IWebHostEnvironment</param>
|
|
public FileController(IFileService fileService, IFileShareService fileShareService, IWebHostEnvironment webHostEnvironment)
|
|
{
|
|
_fileService = fileService;
|
|
_fileShareService = fileShareService;
|
|
_webHostEnvironment = webHostEnvironment;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Datei zurück
|
|
/// </summary>
|
|
/// <param name="container">Container</param>
|
|
/// <param name="filename">Dateiname inkl. Pfad (relativ)</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[HttpGet("{container}/{*filename}")]
|
|
[ResponseCache(Duration = 300, VaryByQueryKeys = new[] { "container", "filename" }, Location = ResponseCacheLocation.Any)]
|
|
//[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public async Task<IActionResult> GetFile(string container, string filename)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(container) && !string.IsNullOrWhiteSpace(filename))
|
|
{
|
|
var file = await _fileService.GetAsync(container, filename);
|
|
var flatFilename = _fileService.GetFlatFilename(filename);
|
|
if (file != null)
|
|
{
|
|
return File(file, GetMimeMapping(flatFilename));
|
|
}
|
|
}
|
|
|
|
return NotFound();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Datei zurück
|
|
/// </summary>
|
|
/// <param name="container">Container</param>
|
|
/// <param name="filename">Dateiname inkl. Pfad (relativ)</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[HttpGet("uncached/{container}/{*filename}")]
|
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public async Task<IActionResult> GetFileUncached(string container, string filename)
|
|
{
|
|
var file = await _fileService.GetAsync(container, filename);
|
|
var flatFilename = _fileService.GetFlatFilename(filename);
|
|
if (file != null)
|
|
{
|
|
return File(file, GetMimeMapping(flatFilename));
|
|
}
|
|
return NotFound();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Datei zurück
|
|
/// </summary>
|
|
/// <param name="share">Share des Mandanten</param>
|
|
/// <param name="path">Dateiname inkl. Pfad (relativ)</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[ApiExplorerSettings(IgnoreApi = true)]
|
|
[Route("~/Browser/", Name = "Browser")]
|
|
[HttpGet("share/{share}/{*path}")]
|
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public IActionResult Browser(string share, string path)
|
|
{
|
|
path = path.TrimStart('/');
|
|
var file = _fileShareService.Get(share, path);
|
|
var flatFilename = path.Split('/').Last();
|
|
if (file != null)
|
|
{
|
|
return File(file, GetMimeMapping(flatFilename));
|
|
}
|
|
return NotFound();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt ein Icon für eine Datei-Extension zurück
|
|
/// </summary>
|
|
/// <param name="ext">Extenstion der Datei</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[HttpGet("extension/{*ext}")]
|
|
[ResponseCache(Duration = 300, VaryByQueryKeys = new[] { "ext" }, Location = ResponseCacheLocation.Any)]
|
|
//[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public IActionResult Extension(string ext)
|
|
{
|
|
if (ext.Contains('.'))
|
|
ext = ext.Replace(".", "");
|
|
|
|
var imageUrl = "/images/FileExtensions/_blank.png";
|
|
if (!string.IsNullOrEmpty(ext))
|
|
{
|
|
imageUrl = "/images/FileExtensions/" + ext + ".png";
|
|
var absolutePath = _webHostEnvironment.WebRootPath + imageUrl;
|
|
if (!System.IO.File.Exists(absolutePath))
|
|
{
|
|
imageUrl = "/images/FileExtensions/_blank.png";
|
|
}
|
|
}
|
|
|
|
var file = System.IO.File.ReadAllBytes(_webHostEnvironment.WebRootPath + imageUrl);
|
|
return File(file, GetMimeMapping(imageUrl));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Datei zurück
|
|
/// </summary>
|
|
/// <param name="share">Share des Mandanten</param>
|
|
/// <param name="path">Dateiname inkl. Pfad (relativ)</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[Route("/scorm/{share}/{*path}", Name = "Scorm")]
|
|
[HttpGet]
|
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public IActionResult GetScorm(string share, string path)
|
|
{
|
|
if (User.Identity.IsAuthenticated)
|
|
{
|
|
path = path.TrimStart('/');
|
|
|
|
var rangeHeader = Request.Headers["Range"];
|
|
if (rangeHeader.Count == 0)
|
|
{
|
|
var fileStream = _fileShareService.GetStream(share, path);
|
|
var flatFilename = path.Split('/').Last();
|
|
if (fileStream != null)
|
|
{
|
|
return File(fileStream, GetMimeMapping(flatFilename), enableRangeProcessing: true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var info = _fileShareService.GetFileInfo(share, path);
|
|
if (info != null)
|
|
{
|
|
var totalLength = info.Size;
|
|
|
|
long start = 0;
|
|
long end = 0;
|
|
|
|
start = GetRangeStartAndEnd(rangeHeader, start, totalLength, ref end);
|
|
long chunkSize = (end - start) + 1;
|
|
|
|
var flatFilename = path.Split('/').Last();
|
|
var fileStream = _fileShareService.GetStream(share, path, start, end);
|
|
if (fileStream != null)
|
|
{
|
|
var result = File(fileStream, GetMimeMapping(flatFilename), enableRangeProcessing: true);
|
|
|
|
|
|
HttpContext.Response.Headers.ContentLength = chunkSize;
|
|
HttpContext.Response.Headers.ContentType = GetMimeMapping(flatFilename);
|
|
HttpContext.Response.Headers.ContentRange = $"bytes {start}-{end}/{totalLength}";
|
|
HttpContext.Response.Headers.AcceptRanges = "bytes";
|
|
HttpContext.Response.StatusCode = 206;
|
|
|
|
return result;
|
|
//return new FileStreamResult(fileStream, GetMimeMapping(flatFilename));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NotFound();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Video-Datei zurück
|
|
/// </summary>
|
|
/// <param name="share">Share des Mandanten</param>
|
|
/// <param name="path">Dateiname inkl. Pfad (relativ)</param>
|
|
/// <returns>Datei oder notFound</returns>
|
|
[Route("/video/{share}/{*path}", Name = "Video")]
|
|
[HttpGet]
|
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public IActionResult GetVideo(string share, string path)
|
|
{
|
|
if (User.Identity.IsAuthenticated)
|
|
{
|
|
path = path.TrimStart('/');
|
|
|
|
var rangeHeader = Request.Headers["Range"];
|
|
if (rangeHeader.Count == 0)
|
|
{
|
|
var fileStream = _fileShareService.GetStream(share, path);
|
|
var flatFilename = path.Split('/').Last();
|
|
if (fileStream != null)
|
|
{
|
|
return File(fileStream, GetMimeMapping(flatFilename), enableRangeProcessing: true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var info = _fileShareService.GetFileInfo(share, path);
|
|
if (info != null)
|
|
{
|
|
var totalLength = info.Size;
|
|
|
|
long start = 0;
|
|
long end = 0;
|
|
|
|
start = GetRangeStartAndEnd(rangeHeader, start, totalLength, ref end);
|
|
long chunkSize = (end - start) + 1;
|
|
|
|
var flatFilename = path.Split('/').Last();
|
|
var fileStream = _fileShareService.GetStream(share, path, start, end);
|
|
if (fileStream != null)
|
|
{
|
|
var result = File(fileStream, GetMimeMapping(flatFilename), enableRangeProcessing: true);
|
|
|
|
|
|
HttpContext.Response.Headers.ContentLength = chunkSize;
|
|
HttpContext.Response.Headers.ContentType = GetMimeMapping(flatFilename);
|
|
HttpContext.Response.Headers.ContentRange = $"bytes {start}-{end}/{totalLength}";
|
|
HttpContext.Response.Headers.AcceptRanges = "bytes";
|
|
HttpContext.Response.StatusCode = 206;
|
|
|
|
return result;
|
|
//return new FileStreamResult(fileStream, GetMimeMapping(flatFilename));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NotFound();
|
|
}
|
|
|
|
private static long GetRangeStartAndEnd(StringValues rangeHeader, long start, long totalLength, ref long end)
|
|
{
|
|
var headerContent = rangeHeader[0];
|
|
if (headerContent.StartsWith("bytes="))
|
|
{
|
|
headerContent = headerContent.Replace("bytes=", "");
|
|
if (headerContent.EndsWith("-"))
|
|
{
|
|
headerContent = headerContent.Replace("-", "");
|
|
start = long.Parse(headerContent);
|
|
end = totalLength - 1;
|
|
}
|
|
else
|
|
{
|
|
var parts = headerContent.Split("-");
|
|
start = long.Parse(parts[0]);
|
|
end = long.Parse(parts[1]);
|
|
}
|
|
}
|
|
|
|
return start;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt den Mimetype einer Datei zurück
|
|
/// </summary>
|
|
/// <param name="fileName">Dateiname</param>
|
|
/// <returns>Mimetype</returns>
|
|
private string GetMimeMapping(string fileName)
|
|
{
|
|
new FileExtensionContentTypeProvider().TryGetContentType(fileName, out var contentType);
|
|
return contentType ?? "application/octet-stream";
|
|
}
|
|
}
|
|
} |