Update zip archive functionality

add download buttons for multiple input/output
This commit is contained in:
2020-07-10 21:06:23 -04:00
parent e4e753c64a
commit 0fd57812e7
4 changed files with 155 additions and 54 deletions
+87 -40
View File
@@ -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);
} }
} }
} }
+37 -9
View File
@@ -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;
}
} }
} }
+22 -5
View File
@@ -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>
} }