< All Topics

Zip multiple files (async)

Overview

The Zip Files (async) function compresses multiple files into a ZIP archive in the background without blocking the main thread. This is the solution for compressing large files or multiple files while maintaining responsive gameplay and UI.

Function Description

Node Name: Zip Files (async)
Category: Archive Manager
Type: Asynchronous (non-blocking operation)

Compresses multiple files in a background thread with real-time progress tracking and completion callbacks. The main thread continues execution immediately while compression happens in the background.

Input Parameters

ParameterTypeDescription
Path to FilesArray of StringsArray containing full absolute paths to all files you want to compress
Path to ZipStringFull absolute path where the ZIP file should be created
Delete After CompressionBooleanIf true, deletes all original files after successful compression
Get ProgressZip Progress DelegateCallback function that receives progress updates (0.0 to 1.0)
CallbackZip Task Complete DelegateCallback function executed when compression completes

Output Parameters

ParameterTypeDescription
Return ValueZip TaskReference to the background task (can be used for cancellation)

Delegate Parameters

ZipProgress (Custom Event)

  • Progress (Float): Compression progress from 0.0 (0%) to 1.0 (100%)

OnZipComplete (Custom Event)

  • Success (Boolean): true if compression succeeded, false if failed
  • Path to Zip File (String): Full path to the created ZIP file (on success)

Setup Steps

1. Create Custom Events for Callbacks

  • ZipProgress Event: Right-click → Add Custom Event → Name: “ZipProgress”
    • Add input parameter: Progress (Float)
  • OnZipComplete Event: Right-click → Add Custom Event → Name: “OnZipComplete”
    • Add input parameter: Success (Boolean)
    • Add input parameter: Path to Zip File (String)

2. Create the File Array

  • Add Make Array node with file paths
  • Example: Single large file F:\Repos\tests\ArchiveManager\asset_file_200mb.psd

3. Add the Zip Files (async) Node

  • Search for “Zip Files (async)”
  • Connect the array to Path to Files
  • Set absolute Path to Zip

4. Connect Progress Tracking

  • Connect ZipProgress custom event to Get Progress delegate
  • Add Format Text node to display progress:
    • Format: "Progress: {Progress}%"
    • Connect Progress × 100 to format parameter

5. Connect Completion Callback

  • Connect OnZipComplete custom event to Callback delegate
  • Add Format Text node to display result:
    • Format: "File zipped and saved at: {Path}"
    • Connect Path to Zip File to format parameter

6. Add Progress Display (Optional)

  • Connect formatted progress text to Print String
  • This provides real-time feedback during compression

Example Blueprint Setup

Advanced Features

Progress Monitoring

The progress callback fires regularly during compression:

  • 0.0: Compression starting
  • 0.5: 50% complete
  • 1.0: Compression finished

Task Reference

The returned Zip Task can be used with:

  • Cancel Current Operation: Stop compression mid-process
  • Task status monitoring
  • Multiple simultaneous operations

Error Handling in Completion Callback

Use Last Archive Error node to access and print errors.

Common Use Cases

Large File Compression

  • Video files, assets, or databases
  • Background compression while user continues working
  • Progress feedback for user experience

Batch Processing

  • Multiple document compression
  • Asset pipeline automation
  • Backup operations

Game Development

  • Save game compression with progress bar
  • Asset bundling for downloadable content
  • User-generated content packaging

Best Practices

User Experience

  1. Always show progress for operations > 2 seconds
  2. Provide cancel option for long operations
  3. Display meaningful status messages
  4. Handle completion gracefully (success/failure feedback)

Performance

  1. Use for files > 10MB or > 50 files
  2. Limit concurrent operations (max 2-3 simultaneous)
  3. Monitor memory usage during compression
  4. Consider file size limits (test with your largest expected files)

Error Handling

  1. Always implement completion callback
  2. Check Success parameter before proceeding
  3. Use Get Last Archive Error for failure details
  4. Validate file paths before starting operation

Threading Notes

  • Main thread continues: UI remains responsive
  • Background processing: Compression runs on worker thread
  • Callback execution: Delegates fire on main thread (safe for UI updates)
  • Memory sharing: Arrays are safely copied to background thread

Cancellation Support

Use Cancel current operation node in level blueprint or pawn controller blueprint to cancel the operation.

Performance Characteristics

  • Startup overhead: ~50ms to initialize background task
  • Memory usage: Peak usage = largest file size + ZIP overhead
  • Progress frequency: Updates every ~100KB processed
  • Completion delay: Callback fires within 1 frame of completion

C++ Usage

Basic Async Implementation

#include "ArchiveManagerBPLibrary.h"

UCLASS()
class MYGAME_API UAsyncCompressionManager : public UObject
{
    GENERATED_BODY()
    
private:
    UZipTask* CurrentTask;
    
public:
    // Start async compression with proper UFunction delegates
    UFUNCTION(BlueprintCallable)
    void CompressLargeFilesAsync()
    {
        // Prepare file list (SAME as original article)
        TArray<FString> LargeFiles;
        LargeFiles.Add(TEXT("C:/LargeAssets/Video.mp4"));
        LargeFiles.Add(TEXT("C:/LargeAssets/Texture.psd"));
        
        FString OutputZip = TEXT("C:/Archives/LargeAssets.zip");
        
        // bind to UFunction instead of lambda
        FZipProgressDelegate ProgressDelegate;
        ProgressDelegate.BindUFunction(this, FName("OnCompressionProgress"));
        
        FZipTaskCompleteDelegate CompleteDelegate;
        CompleteDelegate.BindUFunction(this, FName("OnCompressionComplete"));
        
        // Start async compression (SAME function call as original)
        CurrentTask = UArchiveManagerBPLibrary::ZipFilesAsync(
            LargeFiles, 
            OutputZip, 
            false, 
            ProgressDelegate, 
            CompleteDelegate
        );
    }
    
    // Progress callback function (required for UFunction binding)
    UFUNCTION()
    void OnCompressionProgress(float Progress)
    {
        float Percentage = Progress * 100.0f;
        UE_LOG(LogTemp, Log, TEXT("Compression Progress: %.1f%%"), Percentage);
        
        // Update UI progress bar here
        OnProgressUpdated.Broadcast(Progress);
    }
    
    // Completion callback function (required for UFunction binding)
    UFUNCTION()
    void OnCompressionComplete(bool bSuccess, const FString& ZipPath)
    {
        if (bSuccess)
        {
            UE_LOG(LogTemp, Log, TEXT("Compression completed: %s"), *ZipPath);
            OnCompressionSuccess.Broadcast(ZipPath);
        }
        else
        {
            FString Error = UArchiveManagerBPLibrary::GetLastArchiveError();
            UE_LOG(LogTemp, Error, TEXT("Compression failed: %s"), *Error);
            OnCompressionFailed.Broadcast(Error);
        }
        
        CurrentTask = nullptr;
    }
    
    // Cancel current operation 
    UFUNCTION(BlueprintCallable)
    void CancelCompression()
    {
        if (CurrentTask)
        {
            UArchiveManagerBPLibrary::Cancel();
            CurrentTask = nullptr;
            UE_LOG(LogTemp, Log, TEXT("Compression cancelled"));
        }
    }
    
    // C++ delegates for UI integration
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProgressUpdated, float, Progress);
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCompressionSuccess, FString, ZipPath);
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCompressionFailed, FString, ErrorMessage);
    
    UPROPERTY(BlueprintAssignable)
    FOnProgressUpdated OnProgressUpdated;
    
    UPROPERTY(BlueprintAssignable)
    FOnCompressionSuccess OnCompressionSuccess;
    
    UPROPERTY(BlueprintAssignable) 
    FOnCompressionFailed OnCompressionFailed;
};

Simple one-shot usage

// For simple cases where you don't need progress tracking
void CompressFilesSimple()
{
    TArray<FString> FilesToCompress = {
        TEXT("C:/Data/File1.txt"),
        TEXT("C:/Data/File2.txt")
    };
    
    FString OutputZip = TEXT("C:/Output/Compressed.zip");
    
    // Create empty delegates for simple usage
    FZipProgressDelegate EmptyProgress;
    FZipTaskCompleteDelegate EmptyComplete;
    
    // Start compression (fire and forget)
    UZipTask* Task = UArchiveManagerBPLibrary::ZipFilesAsync(
        FilesToCompress,
        OutputZip,
        false,
        EmptyProgress,
        EmptyComplete
    );
    
    // Optional: Store task reference for cancellation
    // UArchiveManagerBPLibrary::Cancel(); // Cancel if needed
}

Integration with Game Save System

UCLASS()
class MYGAME_API USaveGameCompressor : public UGameInstanceSubsystem
{
    GENERATED_BODY()
    
public:
    // Async save game compression
    UFUNCTION(BlueprintCallable)
    void CompressSaveGamesAsync()
    {
        // Collect all save files (SAME as original article)
        TArray<FString> SaveFiles;
        FString SaveDir = FPaths::ProjectSavedDir() / TEXT("SaveGames");
        IFileManager::Get().FindFiles(SaveFiles, *SaveDir, TEXT("*.sav"), true, false);
        
        // Convert to full paths (SAME as original)
        TArray<FString> FullPaths;
        for (const FString& SaveFile : SaveFiles)
        {
            FullPaths.Add(SaveDir / SaveFile);
        }
        
        if (FullPaths.Num() == 0)
        {
            UE_LOG(LogTemp, Warning, TEXT("No save files found"));
            return;
        }
        
        // Create timestamped backup (SAME as original)
        FString BackupName = FString::Printf(TEXT("SaveBackup_%s.zip"), 
            *FDateTime::Now().ToString(TEXT("%Y%m%d_%H%M%S")));
        FString BackupPath = FPaths::ProjectSavedDir() / TEXT("Backups") / BackupName;
        
        // Ensure backup directory exists
        IFileManager::Get().MakeDirectory(*FPaths::GetPath(BackupPath), true);
        
        // Setup progress tracking with UFunction binding
        FZipProgressDelegate ProgressDelegate;
        ProgressDelegate.BindUFunction(this, FName("OnBackupProgress"));
        
        //  Setup completion callback with UFunction binding
        FZipTaskCompleteDelegate CompleteDelegate;
        CompleteDelegate.BindUFunction(this, FName("OnBackupComplete"));
        
        // Start async compression (SAME function call as original)
        UArchiveManagerBPLibrary::ZipFilesAsync(FullPaths, BackupPath, false, ProgressDelegate, CompleteDelegate);
    }
    
    // Progress callback (required for UFunction binding)
    UFUNCTION()
    void OnBackupProgress(float Progress)
    {
        // Update loading screen or progress bar
        if (GEngine)
        {
            GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, 
                FString::Printf(TEXT("Backup Progress: %.0f%%"), Progress * 100.0f));
        }
    }
    
    // Completion callback (SAME logic as original)
    UFUNCTION()
    void OnBackupComplete(bool bSuccess, const FString& BackupPath)
    {
        if (bSuccess)
        {
            UE_LOG(LogTemp, Log, TEXT("Save game backup completed: %s"), *BackupPath);
            // Notify UI or save system
        }
        else
        {
            UE_LOG(LogTemp, Error, TEXT("Save game backup failed"));
        }
    }
};
Table of Contents