Update zip archive functionality
add download buttons for multiple input/output
This commit is contained in:
+87
-40
@@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using LeafWeb.Core.Utility;
|
||||||
|
|
||||||
namespace LeafWeb.Core.Entities
|
namespace LeafWeb.Core.Entities
|
||||||
{
|
{
|
||||||
@@ -133,56 +134,102 @@ namespace LeafWeb.Core.Entities
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Id}_{Identifier}";
|
return $"{Id}_{Identifier}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains all output files in a zip
|
/// Contains all output files in a zip
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] GetOutputFileZip(LeafOutputFileType? fileType)
|
public byte[] GetOutputFileZip(LeafOutputFileType? fileType)
|
||||||
{
|
{
|
||||||
using (var compressedFileStream = new MemoryStream())
|
return NewMemoryZipArchive((archive, stream) =>
|
||||||
{
|
CompressOutputFiles(
|
||||||
using (var archive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, true))
|
OutputFiles.Where(f => !fileType.HasValue || f.FileType == fileType.Value),
|
||||||
{
|
archive));
|
||||||
foreach (var outputFile in OutputFiles.Where(f => !fileType.HasValue || f.FileType == fileType.Value))
|
|
||||||
{
|
|
||||||
var entry = archive.CreateEntry(outputFile.Filename);
|
|
||||||
using (var originalFileStream = new MemoryStream(outputFile.FileContents.Contents))
|
|
||||||
using (var entryStream = entry.Open())
|
|
||||||
originalFileStream.CopyTo(entryStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return compressedFileStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Contains all input files in a zip
|
|
||||||
/// </summary>
|
|
||||||
public byte[] GetInputFileZip()
|
|
||||||
{
|
|
||||||
using (var compressedFileStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
using (var archive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, true))
|
|
||||||
{
|
|
||||||
foreach (var inputFile in InputFiles)
|
|
||||||
{
|
|
||||||
var entry = archive.CreateEntry(inputFile.Filename);
|
|
||||||
using (var originalFileStream = new MemoryStream(inputFile.Contents))
|
|
||||||
using (var entryStream = entry.Open())
|
|
||||||
originalFileStream.CopyTo(entryStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return compressedFileStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOutputFileSizeSum()
|
/// <summary>
|
||||||
|
/// Contains all input files in a zip
|
||||||
|
/// </summary>
|
||||||
|
public byte[] GetInputFileZip() =>
|
||||||
|
NewMemoryZipArchive((archive, stream) => CompressInputFiles(InputFiles, archive));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains all input files in a zip, ordered into directories
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] GetInputFilesZip(IEnumerable<LeafInput> leafInputs) =>
|
||||||
|
NewMemoryZipArchive((archive, stream) =>
|
||||||
|
{
|
||||||
|
var inputs = leafInputs.ToList();
|
||||||
|
|
||||||
|
foreach (var leafInput in inputs)
|
||||||
|
{
|
||||||
|
var directory = $"{leafInput.Added:yyyy-dd-MM--HH-mm}_{leafInput.Identifier.FilterValidFilename()}";
|
||||||
|
CompressInputFiles(leafInput.InputFiles, archive, directory);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains all input files in a zip, ordered into directories
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] GetOutputFilesZip_ToUser(IEnumerable<LeafInput> leafInputs) =>
|
||||||
|
NewMemoryZipArchive((archive, stream) =>
|
||||||
|
{
|
||||||
|
var inputs = leafInputs.ToList();
|
||||||
|
|
||||||
|
foreach (var leafInput in inputs)
|
||||||
|
{
|
||||||
|
if (stream.Length > 2560000L)
|
||||||
|
continue;
|
||||||
|
var directory = $"{leafInput.Added:yyyy-dd-MM--HH-mm}_{leafInput.Identifier.FilterValidFilename()}";
|
||||||
|
CompressOutputFiles(leafInput.OutputFiles.Where(f => f.FileType == LeafOutputFileType.ToUser), archive, directory);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private static byte[] NewMemoryZipArchive(Action<ZipArchive, MemoryStream> addFiles)
|
||||||
|
{
|
||||||
|
using (var compressedFileStream = new MemoryStream())
|
||||||
|
using (var archive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, true))
|
||||||
|
{
|
||||||
|
addFiles(archive, compressedFileStream);
|
||||||
|
return compressedFileStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long CompressInputFiles(IEnumerable<LeafInputFile> inputFiles, ZipArchive archive, string prefix = "")
|
||||||
|
{
|
||||||
|
var contentsLength = 0L;
|
||||||
|
foreach (var inputFile in inputFiles)
|
||||||
|
{
|
||||||
|
contentsLength += inputFile.Contents.LongLength;
|
||||||
|
var entry = archive.CreateEntry(Path.Combine(prefix, inputFile.Filename));
|
||||||
|
using (var originalFileStream = new MemoryStream(inputFile.Contents))
|
||||||
|
using (var entryStream = entry.Open())
|
||||||
|
originalFileStream.CopyTo(entryStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentsLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long CompressOutputFiles(IEnumerable<LeafOutputFile> outputFiles, ZipArchive archive, string prefix = "")
|
||||||
|
{
|
||||||
|
var contentsLength = 0L;
|
||||||
|
foreach (var outputFile in outputFiles)
|
||||||
|
{
|
||||||
|
contentsLength += outputFile.FileContents.Contents.LongLength;
|
||||||
|
var entry = archive.CreateEntry(Path.Combine(prefix, outputFile.Filename));
|
||||||
|
using (var originalFileStream = new MemoryStream(outputFile.FileContents.Contents))
|
||||||
|
using (var entryStream = entry.Open())
|
||||||
|
originalFileStream.CopyTo(entryStream);
|
||||||
|
}
|
||||||
|
return contentsLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetOutputFileSizeSum()
|
||||||
{
|
{
|
||||||
return OutputFiles.Sum(o => o.FileContents.Contents.Length);
|
return OutputFiles.Sum(o => o.FileContents.Contents.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Caching;
|
using System.Web.Caching;
|
||||||
@@ -92,7 +93,7 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return serviceDescription;
|
return serviceDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Details(int id)
|
public ActionResult Details(int id)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
|
|
||||||
@@ -106,27 +107,37 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult DownloadInput(int id)
|
public ActionResult DownloadInput(int id)
|
||||||
{
|
{
|
||||||
return GetInputZip(id);
|
return GetInputZip(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult DownloadOutputToUser(int id)
|
public ActionResult DownloadOutputToUser(int id)
|
||||||
{
|
{
|
||||||
return GetOutputZip(id, LeafOutputFileType.ToUser);
|
return GetOutputZip(id, LeafOutputFileType.ToUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult DownloadOutputNotToUser(int id)
|
public ActionResult DownloadOutputNotToUser(int id)
|
||||||
{
|
{
|
||||||
return GetOutputZip(id, LeafOutputFileType.NotToUser);
|
return GetOutputZip(id, LeafOutputFileType.NotToUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult DownloadOutputCleanedInput(int id)
|
public ActionResult DownloadOutputCleanedInput(int id)
|
||||||
{
|
{
|
||||||
return GetOutputZip(id, LeafOutputFileType.CleanedInput);
|
return GetOutputZip(id, LeafOutputFileType.CleanedInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionResult GetOutputZip(int id, LeafOutputFileType type)
|
public ActionResult DownloadResultsInputZip(LeafDataQuery q)
|
||||||
|
{
|
||||||
|
return GetResults(q, LeafInput.GetInputFilesZip, $"LeafWeb_{DateTime.Now:yyyy-dd-MM--HH-mm-ss}_Input.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionResult DownloadResultsOutputZip(LeafDataQuery q)
|
||||||
|
{
|
||||||
|
return GetResults(q, LeafInput.GetOutputFilesZip_ToUser, $"LeafWeb_{DateTime.Now:yyyy-dd-MM--HH-mm-ss}_Output.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionResult GetOutputZip(int id, LeafOutputFileType type)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
|
|
||||||
@@ -140,7 +151,7 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionResult GetInputZip(int id)
|
private ActionResult GetInputZip(int id)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
|
|
||||||
@@ -154,7 +165,24 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
||||||
}
|
}
|
||||||
|
|
||||||
[ActionLog]
|
private ActionResult GetResults(LeafDataQuery query, Func<IEnumerable<LeafInput>, byte[]> getZip, string filename)
|
||||||
|
{
|
||||||
|
var resultItems =
|
||||||
|
DataService.GetLeafInputsOrdered();
|
||||||
|
|
||||||
|
resultItems = QueryFilter.Search(resultItems, query);
|
||||||
|
|
||||||
|
if (resultItems == null)
|
||||||
|
return View("DownloadNotFound");
|
||||||
|
|
||||||
|
var zip = getZip(resultItems);
|
||||||
|
|
||||||
|
//var filename = $"LeafWeb_{DateTime.Now:yyyy-dd-MM--HH-mm-ss}_Input.zip";
|
||||||
|
|
||||||
|
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
||||||
|
}
|
||||||
|
|
||||||
|
[ActionLog]
|
||||||
public ActionResult Delete(int id)
|
public ActionResult Delete(int id)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
@@ -178,7 +206,7 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return RedirectToUmbracoPage(LeafWebPageIds.ManageQueue);
|
return RedirectToUmbracoPage(LeafWebPageIds.ManageQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ActionLog]
|
[ActionLog]
|
||||||
public ActionResult Cancel(int id)
|
public ActionResult Cancel(int id)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
using System.Web.Routing;
|
||||||
|
|
||||||
namespace LeafWeb.WebCms.Utility
|
namespace LeafWeb.WebCms.Utility
|
||||||
{
|
{
|
||||||
@@ -27,5 +28,13 @@ namespace LeafWeb.WebCms.Utility
|
|||||||
|
|
||||||
return nvs;
|
return nvs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection nvc)
|
||||||
|
{
|
||||||
|
var routeValues = new RouteValueDictionary();
|
||||||
|
foreach (var key in nvc.AllKeys)
|
||||||
|
routeValues.Add(key, nvc[key]);
|
||||||
|
return routeValues;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,8 @@
|
|||||||
|
|
||||||
@if (Model.Items.Any())
|
@if (Model.Items.Any())
|
||||||
{
|
{
|
||||||
|
@DownloadResultsInput()
|
||||||
|
@DownloadResultsOutput_ToUser()
|
||||||
<div id="queue" class="table-responsive mt-3">
|
<div id="queue" class="table-responsive mt-3">
|
||||||
@grid.Table(columns:
|
@grid.Table(columns:
|
||||||
grid.Columns(
|
grid.Columns(
|
||||||
@@ -155,14 +157,14 @@ else
|
|||||||
|
|
||||||
@helper DetailsLink(dynamic item)
|
@helper DetailsLink(dynamic item)
|
||||||
{
|
{
|
||||||
var cssClass= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
var cssClass = CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
||||||
|
|
||||||
@Html.Partial("DisplayTemplates/_DetailsLink", (int)item.Id, cssClass)
|
@Html.Partial("DisplayTemplates/_DetailsLink", (int)item.Id, cssClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
@helper ChartLink(dynamic item)
|
@helper ChartLink(dynamic item)
|
||||||
{
|
{
|
||||||
var cssClass= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
var cssClass = CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
||||||
|
|
||||||
if (!item.HasLeafChart)
|
if (!item.HasLeafChart)
|
||||||
{
|
{
|
||||||
@@ -224,7 +226,7 @@ else
|
|||||||
}
|
}
|
||||||
@helper DeleteLink(LeafInput item)
|
@helper DeleteLink(LeafInput item)
|
||||||
{
|
{
|
||||||
var cssClass
|
var cssClass
|
||||||
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
||||||
if (!item.IsDeletable)
|
if (!item.IsDeletable)
|
||||||
{
|
{
|
||||||
@@ -235,7 +237,7 @@ else
|
|||||||
|
|
||||||
@helper CancelLink(LeafInput item)
|
@helper CancelLink(LeafInput item)
|
||||||
{
|
{
|
||||||
var cssClass
|
var cssClass
|
||||||
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
||||||
if (!item.IsCancellable)
|
if (!item.IsCancellable)
|
||||||
{
|
{
|
||||||
@@ -246,7 +248,7 @@ else
|
|||||||
|
|
||||||
@helper PriorityForm(LeafInput item, Priority priority)
|
@helper PriorityForm(LeafInput item, Priority priority)
|
||||||
{
|
{
|
||||||
var cssClass
|
var cssClass
|
||||||
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
= CssClassUtil.CreateCssClassDataDictionary("dropdown-item");
|
||||||
|
|
||||||
@Html.Partial("DisplayTemplates/_PriorityForm", Tuple.Create(item.Id, item.PendingPriority, priority), cssClass)
|
@Html.Partial("DisplayTemplates/_PriorityForm", Tuple.Create(item.Id, item.PendingPriority, priority), cssClass)
|
||||||
@@ -256,4 +258,19 @@ else
|
|||||||
{
|
{
|
||||||
if (disabled)
|
if (disabled)
|
||||||
{<text>disabled</text>}
|
{<text>disabled</text>}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@helper DownloadResultsInput()
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("DownloadResultsInputZip", "Queue", Model.Q.GetNameValueCollection().ToRouteValueDictionary())">
|
||||||
|
<span class="fa fa-download"></span> Input
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
|
||||||
|
@helper DownloadResultsOutput_ToUser()
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("DownloadResultsOutputZip", "Queue", Model.Q.GetNameValueCollection().ToRouteValueDictionary())">
|
||||||
|
<span class="fa fa-download"></span> Output
|
||||||
|
</a>
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user