using FileFlows.Plugin; using FileFlows.Plugin.Attributes; using System.IO.Compression; using System.IO; using FileFlows.Plugin.Helpers; namespace FileFlows.BasicNodes.File; /// /// A flow element that zips files or directories. /// public class Zip : Node { /// /// Gets the number of inputs /// public override int Inputs => 1; /// /// Gets the number of outputs /// public override int Outputs => 1; /// /// Gets the element type /// public override FlowElementType Type => FlowElementType.Process; /// /// Gets the icon /// public override string Icon => "fas fa-file-archive"; /// /// Gets the help URL /// public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/zip"; private string _DestinationPath = string.Empty; private string _DestinationFile = string.Empty; /// /// Gets or sets the destination path for zipping. /// [Folder(1)] public string DestinationPath { get => _DestinationPath; set { _DestinationPath = value ?? ""; } } /// /// Gets or sets the destination file name for zipping. /// [TextVariable(2)] public string DestinationFile { get => _DestinationFile; set { _DestinationFile = value ?? ""; } } /// /// Executes the flow element /// /// the node parameters /// the output to call next public override int Execute(NodeParameters args) { bool isDir = false; try { if (args.FileService.DirectoryExists(args.WorkingFile).Is(true)) { isDir = true; } else if (args.FileService.FileExists(args.WorkingFile).Is(true) == false) { args.Logger?.ELog("File or folder does not exist: " + args.WorkingFile); return -1; } string destDir = DestinationPath; if (string.IsNullOrEmpty(destDir)) { if (isDir) destDir = FileHelper.GetDirectory(args.LibraryPath); else destDir = FileHelper.GetDirectory(args.FileName); if (string.IsNullOrEmpty(destDir)) { args.Logger?.ELog("Failed to get destination directory"); return -1; } } else { // in case they set a linux path on windows or vice versa destDir = destDir.Replace('\\', args.FileService.PathSeparator); destDir = destDir.Replace('/', args.FileService.PathSeparator); destDir = args.ReplaceVariables(destDir, stripMissing: true); // this converts it to the actual OS path destDir = FileHelper.GetDirectory(destDir); args.FileService.DirectoryCreate(destDir); } string destFile = args.ReplaceVariables(DestinationFile ?? string.Empty, true); if (string.IsNullOrEmpty(destFile)) { destFile = FileHelper.GetShortFileName(args.FileName) + ".zip"; } if (destFile.ToLower().EndsWith(".zip") == false) destFile += ".zip"; destFile = FileHelper.Combine(destDir, destFile); string tempZip = FileHelper.Combine(args.TempPath, Guid.NewGuid() + ".zip"); args.Logger?.ILog($"Compressing '{args.WorkingFile}' to '{destFile}'"); if (isDir) { if (args.FileService.FileIsLocal(args.WorkingFile) == false) { args.Logger?.ELog("Cannot zip remote directories"); return -1; } var dir = new DirectoryInfo(args.WorkingFile); var files = dir.GetFiles("*.*", SearchOption.AllDirectories); using FileStream fs = new FileStream(tempZip, FileMode.Create); using ZipArchive arch = new ZipArchive(fs, ZipArchiveMode.Create); args?.PartPercentageUpdate(0); float current = 0; float count = files.Length; foreach (var file in files) { ++count; if (string.Equals(file.FullName, destFile, StringComparison.CurrentCultureIgnoreCase)) continue; // cant zip the zip we are creating string relative = file.FullName[(dir.FullName.Length + 1)..]; try { arch.CreateEntryFromFile(file.FullName, relative, CompressionLevel.SmallestSize); } catch (Exception ex) { args.Logger?.WLog("Failed to add file to zip: " + file.FullName + " => " + ex.Message); } args?.PartPercentageUpdate((current / count) * 100); } args?.PartPercentageUpdate(100); } else { string localFile = args.FileService.GetLocalPath(args.WorkingFile); using FileStream fs = new FileStream(tempZip, FileMode.Create); using ZipArchive arch = new ZipArchive(fs, ZipArchiveMode.Create); arch.CreateEntryFromFile(localFile, FileHelper.GetShortFileName(args.LibraryFileName)); } if (System.IO.File.Exists(tempZip) == false) { args.Logger?.ELog("Failed to create zip: " + destFile); return -1; } if (args.FileService.FileMove(tempZip, destFile, true).Failed(out string error)) { args.Logger?.ELog("Failed to move zip: " + error); return -1; } args.SetWorkingFile(destFile); args.Logger?.ILog("Zip created at: " + destFile); return 1; } catch (Exception ex) { args.Logger?.ELog("Failed creating zip: " + ex.Message + Environment.NewLine + ex.StackTrace); return -1; } } }