// Copyright Epic Games, Inc. All Rights Reserved.
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace HordeServer.Utilities
{
///
/// Class deriving from a FileResult that allows custom file types (used for zip file creation)
///
public class CustomFileCallbackResult : FileResult
{
private readonly Func _callback;
readonly string _fileName;
readonly bool _inline;
///
/// Constructor
///
/// Default filename for the downloaded file
/// Content type for the file
/// Whether to display the file inline in the browser
/// Callback used to write the data
public CustomFileCallbackResult(string fileName, string mimeType, bool inline, Func callback)
: base(mimeType)
{
_fileName = fileName;
_inline = inline;
_callback = callback;
}
///
/// Executes the action result
///
/// The controller context
///
public override Task ExecuteResultAsync(ActionContext context)
{
ContentDisposition contentDisposition = new ContentDisposition();
contentDisposition.Inline = _inline;
contentDisposition.FileName = _fileName;
context.HttpContext.Response.Headers["Content-Disposition"] = contentDisposition.ToString();
CustomFileCallbackResultExecutor executor = new CustomFileCallbackResultExecutor(context.HttpContext.RequestServices.GetRequiredService());
return executor.ExecuteAsync(context, this);
}
///
/// Exectutor for the custom FileResult
///
private sealed class CustomFileCallbackResultExecutor : FileResultExecutorBase
{
///
/// Constructor
///
/// The logger
public CustomFileCallbackResultExecutor(ILoggerFactory loggerFactory)
: base(CreateLogger(loggerFactory))
{
}
///
/// Executes a CustomFileResult callback
///
/// The controller context
/// The custom file result
///
public Task ExecuteAsync(ActionContext context, CustomFileCallbackResult result)
{
SetHeadersAndLog(context, result, null, false);
return result._callback(context.HttpContext.Response.Body, context);
}
}
}
///
/// Stream overriding CanSeek to false so the zip file plays nice with it.
///
public class CustomBufferStream : MemoryStream
{
///
/// Always report unseekable.
///
public override bool CanSeek => false;
}
}