204 lines
8.7 KiB
C#
204 lines
8.7 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.Extensions.Logging;
|
|
using AyaNova.Models;
|
|
using AyaNova.Api.ControllerHelpers;
|
|
using AyaNova.Util;
|
|
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Microsoft.AspNetCore.Http.Features;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.AspNetCore.WebUtilities;
|
|
using Microsoft.Net.Http.Headers;
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//************************************************************************************************************** */
|
|
//JUNE 19th 2018 LARGE FILE UPLOAD POSSIBLY NEW INFO HERE:
|
|
//http://www.talkingdotnet.com/how-to-increase-file-upload-size-asp-net-core/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
namespace AyaNova.Api.Controllers
|
|
{
|
|
|
|
|
|
//FROM DOCS HERE:
|
|
//https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
|
|
//https://github.com/aspnet/Docs/tree/74a44669d5e7039e2d4d2cb3f8b0c4ed742d1124/aspnetcore/mvc/models/file-uploads/sample/FileUploadSample
|
|
|
|
|
|
/// <summary>
|
|
/// Backup and restore controller for uploading or downloading backup files
|
|
/// and triggering a restore from backup
|
|
///
|
|
/// </summary>
|
|
[ApiVersion("8.0")]
|
|
[Route("api/v{version:apiVersion}/[controller]")]
|
|
[Produces("application/json")]
|
|
[Authorize]
|
|
public class BackupController : Controller
|
|
{
|
|
private readonly AyContext ct;
|
|
private readonly ILogger<BackupController> log;
|
|
private readonly ApiServerState serverState;
|
|
|
|
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="dbcontext"></param>
|
|
/// <param name="logger"></param>
|
|
/// <param name="apiServerState"></param>
|
|
public BackupController(AyContext dbcontext, ILogger<BackupController> logger, ApiServerState apiServerState)
|
|
{
|
|
ct = dbcontext;
|
|
log = logger;
|
|
serverState = apiServerState;
|
|
}
|
|
|
|
/*
|
|
LOOKAT:
|
|
A backup archive consists of a similar format to the v7 data dumper utility, json file per object in subdirectories corresponding to object type all in a zip archive
|
|
|
|
Route to trigger restore from selected file
|
|
Route to force immediate backup
|
|
Backup code in biz objects "IBackup" interface (which in turn is probably going to implement an IExport interface as it serves dual purpose
|
|
of exporting data, or maybe that's special purpose custom objects for exporting like csv etc since there is likely a graph of data involved)
|
|
- object is exported / backed up to json
|
|
Restore code in biz objects "IRestore" interface
|
|
- object(s) imported via restore and data given to them or file or whatever (See discource project)
|
|
|
|
*/
|
|
|
|
//TODO: Copy the code from ImportAyaNova7Controller upload method instead of this old crap
|
|
|
|
// /// <summary>
|
|
// /// Upload AyaNova backup files
|
|
// /// **Files of the same name will overwrite without warning**
|
|
// /// Maximum 10gb
|
|
// /// </summary>
|
|
// /// <returns></returns>
|
|
// [HttpPost("Upload")]
|
|
// [DisableFormValueModelBinding]
|
|
// [RequestSizeLimit(10737418241)]//10737418240 = 10gb https://github.com/aspnet/Announcements/issues/267
|
|
// public async Task<IActionResult> Upload()
|
|
// {
|
|
// //Adapted from the example found here: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
|
|
|
|
// try
|
|
// {
|
|
// if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
|
|
// {
|
|
// return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}"));
|
|
// }
|
|
|
|
// // Used to accumulate all the form url encoded key value pairs in the
|
|
// // request.
|
|
// var formAccumulator = new KeyValueAccumulator();
|
|
// //string targetFilePath = null;
|
|
|
|
// var boundary = MultipartRequestHelper.GetBoundary(
|
|
// MediaTypeHeaderValue.Parse(Request.ContentType),
|
|
// _defaultFormOptions.MultipartBoundaryLengthLimit);
|
|
// var reader = new MultipartReader(boundary, HttpContext.Request.Body);
|
|
|
|
// var section = await reader.ReadNextSectionAsync();
|
|
|
|
// while (section != null)
|
|
// {
|
|
// ContentDispositionHeaderValue contentDisposition;
|
|
// var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
|
|
|
|
// if (hasContentDispositionHeader)
|
|
// {
|
|
// if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
|
|
// {
|
|
// //Save file
|
|
// //as it's just a backup file there is no db involvement at all
|
|
// FileUtil.storeBackupFile(section.Body, contentDisposition.FileName.Value.Replace("\"",""));
|
|
|
|
|
|
// }
|
|
// else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
|
|
// {
|
|
// // Content-Disposition: form-data; name="key"
|
|
// //
|
|
// // value
|
|
|
|
// // Do not limit the key name length here because the
|
|
// // multipart headers length limit is already in effect.
|
|
// var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
|
|
// var encoding = GetEncoding(section);
|
|
// using (var streamReader = new StreamReader(
|
|
// section.Body,
|
|
// encoding,
|
|
// detectEncodingFromByteOrderMarks: true,
|
|
// bufferSize: 1024,
|
|
// leaveOpen: true))
|
|
// {
|
|
// // The value length limit is enforced by MultipartBodyLengthLimit
|
|
// var value = await streamReader.ReadToEndAsync();
|
|
// if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
|
|
// {
|
|
// value = String.Empty;
|
|
// }
|
|
// formAccumulator.Append(key.Value, value);
|
|
|
|
// if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
|
|
// {
|
|
// throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // Drains any remaining section body that has not been consumed and
|
|
// // reads the headers for the next section.
|
|
// section = await reader.ReadNextSectionAsync();
|
|
// }
|
|
|
|
|
|
|
|
|
|
// }
|
|
// catch (InvalidDataException ex)
|
|
// {
|
|
// return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", ex.Message));
|
|
// }
|
|
|
|
// return Ok();
|
|
// }
|
|
|
|
|
|
// private static Encoding GetEncoding(MultipartSection section)
|
|
// {
|
|
// MediaTypeHeaderValue mediaType;
|
|
// var hasMediaTypeHeader = MediaTypeHeaderValue.TryParse(section.ContentType, out mediaType);
|
|
// // UTF-7 is insecure and should not be honored. UTF-8 will succeed in
|
|
// // most cases.
|
|
// if (!hasMediaTypeHeader || Encoding.UTF7.Equals(mediaType.Encoding))
|
|
// {
|
|
// return Encoding.UTF8;
|
|
// }
|
|
// return mediaType.Encoding;
|
|
// }
|
|
|
|
|
|
}//eoc
|
|
}//eons
|