diff --git a/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs b/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs
index bd3671a6..c80498d6 100644
--- a/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs
+++ b/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs
@@ -23,36 +23,16 @@ namespace AyaNova.Api.ControllerHelpers
internal static class ApiUploadProcessor
{
- ///
- /// Process uploaded attachment file
- /// Will be treated as a temporary file for further processing into database
- ///
- ///
- ///
- internal static async Task ProcessAttachmentUploadAsync(Microsoft.AspNetCore.Http.HttpContext httpContext)
- {
- return await ProcessUploadAsync(httpContext, true);
- }
- ///
- /// Process uploaded utility file (backup)
- /// Anything that will be stored in the backup folder as is
- ///
- ///
- ///
- internal static async Task ProcessUtilityFileUploadAsync(Microsoft.AspNetCore.Http.HttpContext httpContext)
- {
- return await ProcessUploadAsync(httpContext, false);
- }
+
///
/// handle upload
///
- ///
- ///
+ ///
/// list of files and form field data (if present)
- private static async Task ProcessUploadAsync(Microsoft.AspNetCore.Http.HttpContext httpContext, bool processAsAttachment)
+ internal static async Task ProcessUploadAsync(Microsoft.AspNetCore.Http.HttpContext httpContext)
{
ApiUploadedFilesResult result = new ApiUploadedFilesResult();
@@ -69,7 +49,6 @@ namespace AyaNova.Api.ControllerHelpers
var section = await reader.ReadNextSectionAsync();
-
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
@@ -83,24 +62,13 @@ namespace AyaNova.Api.ControllerHelpers
string filePathAndName = string.Empty;
var CleanedUploadFileName = contentDisposition.FileName.Value.Replace("\"", "");
- if (processAsAttachment)
- {
- //get temp file path and temp file name
- filePathAndName = FileUtil.NewRandomAttachmentFileName;
- }
- else
- {
- //store directly into the backup file folder
- //NOTE: all utility files are always stored as lowercase to avoid recognition issues down the road
- CleanedUploadFileName = CleanedUploadFileName.ToLowerInvariant();
- filePathAndName = FileUtil.GetFullPathForUtilityFile(CleanedUploadFileName);
- }
-
+ //get temp file path and temp file name
+ filePathAndName = FileUtil.NewRandomUserFilesFolderFileName;
//save to disk
using (var stream = new FileStream(filePathAndName, FileMode.Create))
{
- await section.Body.CopyToAsync(stream);
+ await section.Body.CopyToAsync(stream);
}
result.UploadedFiles.Add(new UploadedFileInfo()
{
diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs
index a8a591eb..5da0efc0 100644
--- a/server/AyaNova/Controllers/AttachmentController.cs
+++ b/server/AyaNova/Controllers/AttachmentController.cs
@@ -165,11 +165,11 @@ namespace AyaNova.Api.Controllers
//used to hold extra file data sent by client
- public class fileData
- {
- public string name { get; set; }
- public long lastModified { get; set; }
- }
+ // public class UploadFileData
+ // {
+ // public string name { get; set; }
+ // public long lastModified { get; set; }
+ // }
///
/// Upload attachment file
@@ -197,14 +197,14 @@ namespace AyaNova.Api.Controllers
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}"));
- var uploadFormData = await ApiUploadProcessor.ProcessAttachmentUploadAsync(HttpContext);
+ var uploadFormData = await ApiUploadProcessor.ProcessUploadAsync(HttpContext);
bool badRequest = false;
string AttachToObjectType = string.Empty;
string AttachToObjectId = string.Empty;
string errorMessage = string.Empty;
string Notes = string.Empty;
- List FileData = new List();
+ List FileData = new List();
if (
!uploadFormData.FormFieldData.ContainsKey("FileData") ||
@@ -222,7 +222,7 @@ namespace AyaNova.Api.Controllers
Notes = uploadFormData.FormFieldData["Notes"].ToString();
//fileData in JSON stringify format which contains the actual last modified dates etc
//"[{\"name\":\"Client.csv\",\"lastModified\":1582822079618},{\"name\":\"wmi4fu06nrs41.jpg\",\"lastModified\":1586900220990}]"
- FileData = Newtonsoft.Json.JsonConvert.DeserializeObject>(uploadFormData.FormFieldData["FileData"].ToString());
+ FileData = Newtonsoft.Json.JsonConvert.DeserializeObject>(uploadFormData.FormFieldData["FileData"].ToString());
if (string.IsNullOrWhiteSpace(AttachToObjectType) || string.IsNullOrWhiteSpace(AttachToObjectId))
{
@@ -298,7 +298,7 @@ namespace AyaNova.Api.Controllers
//Get the actual date from the separate filedata
//this is because the lastModified date is always empty in the form data files
DateTime theDate = DateTime.MinValue;
- foreach (fileData f in FileData)
+ foreach (UploadFileData f in FileData)
{
if (f.name == a.OriginalFileName)
{
diff --git a/server/AyaNova/Controllers/TranslationController.cs b/server/AyaNova/Controllers/TranslationController.cs
index f7ed7ff7..c28a52d5 100644
--- a/server/AyaNova/Controllers/TranslationController.cs
+++ b/server/AyaNova/Controllers/TranslationController.cs
@@ -15,6 +15,7 @@ using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Linq;
+using AyaNova.Util;
@@ -304,12 +305,11 @@ namespace AyaNova.Api.Controllers
var asText = Newtonsoft.Json.JsonConvert.SerializeObject(
o,
Newtonsoft.Json.Formatting.None,
- new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(new string[] { "Concurrency", "Id","TranslationId" }) });
+ new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "TranslationId" }) });
var bytes = System.Text.Encoding.UTF8.GetBytes(asText);
var file = new FileContentResult(bytes, "application/octet-stream");
file.FileDownloadName = Util.FileUtil.StringToSafeFileName(o.Name) + ".json";
return file;
-
}
@@ -336,6 +336,104 @@ namespace AyaNova.Api.Controllers
+ ///
+ /// Upload Translation export file
+ /// Max 15mb total
+ ///
+ /// Accepted
+ [Authorize]
+ [HttpPost("upload")]
+ [DisableFormValueModelBinding]
+ [RequestSizeLimit(15000000)]//currently export file is 200kb * 50 maximum at a time = 15mb https://github.com/aspnet/Announcements/issues/267
+ public async Task UploadAsync()
+ {
+ //Adapted from the example found here: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
+
+ if (!serverState.IsOpen)
+ return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
+
+ // var returnList = new List();
+ object ret = null;
+ AyaTypeId attachToObject = null;
+ try
+ {
+ if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
+ return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}"));
+
+ var uploadFormData = await ApiUploadProcessor.ProcessUploadAsync(HttpContext);
+
+ bool badRequest = false;
+ string UploadObjectType = string.Empty;
+ string UploadObjectId = string.Empty;
+ string errorMessage = string.Empty;
+ string Notes = string.Empty;
+ List FileData = new List();
+
+ if (
+ !uploadFormData.FormFieldData.ContainsKey("FileData"))//only filedata is required
+ {
+ badRequest = true;
+ errorMessage = "Missing required FormFieldData value: FileData";
+ }
+ if (!badRequest)
+ {
+ if (uploadFormData.FormFieldData.ContainsKey("ObjectType"))
+ UploadObjectType = uploadFormData.FormFieldData["ObjectType"].ToString();
+ if (uploadFormData.FormFieldData.ContainsKey("ObjectId"))
+ UploadObjectId = uploadFormData.FormFieldData["ObjectId"].ToString();
+ if (uploadFormData.FormFieldData.ContainsKey("Notes"))
+ Notes = uploadFormData.FormFieldData["Notes"].ToString();
+ //fileData in JSON stringify format which contains the actual last modified dates etc
+ //"[{\"name\":\"Client.csv\",\"lastModified\":1582822079618},{\"name\":\"wmi4fu06nrs41.jpg\",\"lastModified\":1586900220990}]"
+ FileData = Newtonsoft.Json.JsonConvert.DeserializeObject>(uploadFormData.FormFieldData["FileData"].ToString());
+
+ }
+
+
+ long UserId = UserIdFromContext.Id(HttpContext.Items);
+
+ //We have our files and a confirmed AyObject, ready to attach and save permanently
+ if (uploadFormData.UploadedFiles.Count > 0)
+ {
+
+ foreach (UploadedFileInfo a in uploadFormData.UploadedFiles)
+ {
+ //Get the actual date from the separate filedata
+ //this is because the lastModified date is always empty in the form data files
+ DateTime theDate = DateTime.MinValue;
+ foreach (UploadFileData f in FileData)
+ {
+ if (f.name == a.OriginalFileName)
+ {
+ if (f.lastModified > 0)
+ {
+ theDate = DateTimeOffset.FromUnixTimeMilliseconds(f.lastModified).DateTime;
+ }
+ }
+ }
+ if (theDate == DateTime.MinValue)
+ theDate = DateTime.UtcNow;
+
+ var v = await FileUtil.StoreFileAttachmentAsync(a.InitialUploadedPathName, a.MimeType, a.OriginalFileName, theDate, attachToObject, Notes, ct);
+
+ //EVENT LOG
+ await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
+
+ //SEARCH INDEXING
+ var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment);
+ SearchParams.AddText(v.Notes).AddText(v.DisplayFileName);
+ await Search.ProcessNewObjectKeywordsAsync(SearchParams);
+ }
+ }
+ }
+ catch (System.IO.InvalidDataException ex)
+ {
+ return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", ex.Message));
+ }
+
+ //Return the list of attachment ids and filenames
+ return Accepted();
+ }
diff --git a/server/AyaNova/models/dto/UploadFileData.cs b/server/AyaNova/models/dto/UploadFileData.cs
new file mode 100644
index 00000000..38d69bb7
--- /dev/null
+++ b/server/AyaNova/models/dto/UploadFileData.cs
@@ -0,0 +1,8 @@
+namespace AyaNova.Models
+{
+ public class UploadFileData
+ {
+ public string name { get; set; }
+ public long lastModified { get; set; }
+ }
+}
diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs
index 5a135021..c33834fc 100644
--- a/server/AyaNova/util/FileUtil.cs
+++ b/server/AyaNova/util/FileUtil.cs
@@ -331,7 +331,7 @@ namespace AyaNova.Util
/// Get a random file name with path to attachments folder
///
///
- internal static string NewRandomAttachmentFileName
+ internal static string NewRandomUserFilesFolderFileName
{
get
{