using System.ComponentModel.DataAnnotations; using FileFlows.BasicNodes.Helpers; using FileFlows.Plugin; using FileFlows.Plugin.Attributes; using FileFlows.Plugin.Helpers; namespace FileFlows.BasicNodes.File; /// /// Node that copies a file /// public class CopyFile : Node { /// /// Gets the number of inputs /// public override int Inputs => 1; /// /// Gets the number of outputs /// public override int Outputs => 1; /// /// Gets the type of node /// public override FlowElementType Type => FlowElementType.Process; /// /// Gets the icon for this node /// public override string Icon => "far fa-copy"; /// /// Gets the help URL /// public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/copy-file"; private string _DestinationPath = string.Empty; private string _DestinationFile = string.Empty; /// /// Gets or sets the input file to move /// [TextVariable(1)] public string InputFile{ get; set; } /// /// Gets or sets the destination path to copy the file to /// [Required] [Folder(2)] public string DestinationPath { get => _DestinationPath; set => _DestinationPath = value ?? string.Empty; } /// /// Gets or sets the destination file /// [TextVariable(3)] public string DestinationFile { get => _DestinationFile; set => _DestinationFile = value ?? string.Empty; } /// /// Gets or sets if the folder structure should be copied /// [Boolean(4)] public bool CopyFolder { get; set; } /// /// Gets or sets additional files to copy /// [StringArray(5)] public string[] AdditionalFiles { get; set; } /// /// Gets or sets if the additional files should be copied from the source location (true) or temporary location (false) /// [Boolean(6)] public bool AdditionalFilesFromOriginal { get; set; } /// /// Gets or sets if the original files creation and last write time dates should be preserved /// [Boolean(7)] public bool PreserverOriginalDates { get; set; } /// public override int Execute(NodeParameters args) { var destParts = MoveFile.GetDestinationPathParts(args, DestinationPath, DestinationFile, CopyFolder); if (destParts.Filename == null) return -1; string inputFile = args.ReplaceVariables(InputFile ?? string.Empty, stripMissing: true)?.EmptyAsNull() ?? args.WorkingFile; // cant use new FileInfo(dest).Directory.Name here since // if the folder is a linux folder and this node is running on windows // /mnt, etc will be converted to c:\mnt and break the destination var destDir = destParts.Path; var destFile = destParts.Filename; if(inputFile != args.WorkingFile && string.IsNullOrWhiteSpace(DestinationFile)) { destFile = FileHelper.GetShortFileName(inputFile); } string dest = FileHelper.Combine(destParts.Path, destFile); //bool copied = args.CopyFile(args.WorkingFile, dest, updateWorkingFile: true); //if (!copied) // return -1; args.Logger?.ILog("File to copy: " + inputFile); args.Logger?.ILog("Destination: " + dest); if (args.CopyFile(inputFile, dest).Failed(out string error)) { args.FailureReason = "Failed to copy file: " + error; args.Logger?.ELog(args.FailureReason); return -1; } if (inputFile == args.WorkingFile) { args.Logger?.ILog("Setting working file to: " + dest); args.SetWorkingFile(dest); if (PreserverOriginalDates) { if (args.Variables.TryGetValue("ORIGINAL_CREATE_UTC", out object oCreateTimeUtc) && args.Variables.TryGetValue("ORIGINAL_LAST_WRITE_UTC", out object oLastWriteUtc) && oCreateTimeUtc is DateTime dtCreateTimeUtc && oLastWriteUtc is DateTime dtLastWriteUtc) { args.Logger?.ILog("Preserving dates"); args.FileService.SetLastWriteTimeUtc(dest, dtLastWriteUtc); args.FileService.SetCreationTimeUtc(dest, dtCreateTimeUtc); } else { args.Logger?.WLog("Preserve dates is on but failed to get original dates from variables"); } } } var srcDir = FileHelper.GetDirectory(AdditionalFilesFromOriginal ? args.FileName : inputFile); if (AdditionalFiles?.Any() == true) { string shortNameLookup = FileHelper.GetShortFileName(AdditionalFilesFromOriginal ? args.FileName : inputFile); if (shortNameLookup.LastIndexOf(".", StringComparison.InvariantCulture) > 0) shortNameLookup = shortNameLookup[..shortNameLookup.LastIndexOf(".", StringComparison.Ordinal)]; args.Logger?.ILog("Additional Files: " + string.Join(", ", AdditionalFiles)); var addFiles = FolderHelper.GetAdditionalFiles(args.Logger, args.FileService, args.ReplaceVariables, shortNameLookup, srcDir, AdditionalFiles); foreach (var addFile in addFiles) { try { string shortName = FileHelper.GetShortFileName(addFile); string addFileDest = destDir + args.FileService.PathSeparator + shortName; args.FileService.FileCopy(addFile, addFileDest, true); args.Logger?.ILog("Copied file: \"" + addFile + "\" to \"" + addFileDest + "\""); } catch (Exception ex) { args.Logger?.ILog("Failed copying file: \"" + addFile + "\": " + ex.Message); } } } // not needed as args.CopyFile does this //args?.SetWorkingFile(dest); return 1; } }