< All Topics

Unzip Single File with Rename (async)

Overview

The Unzip Single File with Rename (async) function extracts a specific file from a zip archive and renames it during extraction. This is perfect for scenarios where you need to extract only one particular file from an archive and give it a new name.

Function Description

  • Node Name: Unzip Single File with Rename (async)
  • Category: Archive Manager
  • Type: Asynchronous (non-blocking operation)

Extracts a specifically named file from a ZIP archive, renames it to your specified filename, and runs the operation in a background thread with real-time progress tracking and completion callbacks.

Blueprint Usage

Input Parameters

ParameterTypeDescription
Path to ZipStringFull absolute path to the ZIP file you want to extract from
Source FilenameStringExact name of the file to extract from the archive (e.g., “config.json”, “subfolder/data.txt”)
Delete After ExtractionBooleanIf true, deletes the ZIP file after successful extraction
Extracted Data FilenameStringNew filename for the extracted file (e.g., “new_asset_file_name.psd”)
Get ProgressZip Progress DelegateCallback function that receives progress updates (0.0 to 1.0)
CallbackUnzip Task Complete DelegateCallback function executed when extraction completes

Output Parameters

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

Delegate Parameters

CustomEvent 1 (Progress Event)

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

CustomEvent 2 (Completion Event)

  • Success (Boolean): true if extraction succeeded, false if failed
  • Path to Files (Array of Strings): Array containing the path to the extracted and renamed file

Blueprint Setup Steps

1. Create Custom Events for Callbacks

  • CustomEvent 1: Right-click → Add Custom Event → Name: “CustomEvent 1”
    • Add input parameter: Progress (Float)
  • CustomEvent 2: Right-click → Add Custom Event → Name: “CustomEvent 2”
    • Add input parameter: Success (Boolean)
    • Add input parameter: Path to Files (Array of Strings)

2. Add the Unzip Single File with Rename (async) Node

  • Search for “Unzip Single File with Rename (async)”
  • Set Path to Zip: “F:/TestData/ArchiveManager/ObjectsArchive.zip”
  • Set Source Filename: “asset_file_200mb.pub”
  • Set Delete After Extraction: ☐ (keep original ZIP file)
  • Set Extracted Data Filename: “new_asset_file_name.pub”

3. Connect Progress Tracking

  • Connect CustomEvent 1 to Get Progress delegate
  • Add Format Text node to display progress:
    • Format: “Unzipping: {Progress}%”
    • Connect Progress × 100 to format parameter

4. Connect Completion Callback

  • Connect CustomEvent 2 to Callback delegate
  • Add For Each Loop to process the extracted file:
    • Connect Path to Files array to For Each Loop input
    • Display the extracted file path using Print String

5. Add Final Completion Message

  • After the For Each Loop, add Print String: “Unzipping complete”

C++ Usage

Basic Implementation

Click to see the code
class YOURGAME_API UBasicUnzipExample : public UObject
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable)
    bool StartUnzipWithRename(const FString& ZipPath, const FString& SourceFile, const FString& NewName);

private:
    UFUNCTION()
    void OnExtractionProgress(float Progress);
    
    UFUNCTION()
    void OnExtractionComplete(bool bSuccess, TArray<FString> ExtractedFiles);
    
    UPROPERTY()
    UZipTask* CurrentTask;
};

bool UBasicUnzipExample::StartUnzipWithRename(const FString& ZipPath, const FString& SourceFile, const FString& NewName)
{
    // Input validation
    if (ZipPath.IsEmpty() || SourceFile.IsEmpty() || NewName.IsEmpty())
    {
        UE_LOG(LogTemp, Error, TEXT("Invalid parameters: all strings must be non-empty"));
        return false;
    }

    // Check if file exists
    if (!FPaths::FileExists(ZipPath))
    {
        UE_LOG(LogTemp, Error, TEXT("Zip file not found: %s"), *ZipPath);
        return false;
    }

    // Setup delegates
    FZipProgressDelegate ProgressDelegate;
    ProgressDelegate.BindUFunction(this, FName("OnExtractionProgress"));

    FUnzipTaskCompleteDelegate CompleteDelegate;
    CompleteDelegate.BindUFunction(this, FName("OnExtractionComplete"));

    // Start extraction with task validation
    CurrentTask = UArchiveManagerBPLibrary::UnzipAsyncWithRename(
        ZipPath,              // Path to zip
        SourceFile,           // Source filename
        false,                // Delete after extraction
        NewName,              // New filename
        ProgressDelegate,     // Progress callback
        CompleteDelegate      // Completion callback
    );

    if (CurrentTask)
    {
        UE_LOG(LogTemp, Log, TEXT("Unzip task started: %s -> %s"), *SourceFile, *NewName);
        return true;
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to create unzip task"));
        return false;
    }
}

void UBasicUnzipExample::OnExtractionProgress(float Progress)
{
    UE_LOG(LogTemp, VeryVerbose, TEXT("Extraction progress: %.1f%%"), Progress * 100.0f);
}

void UBasicUnzipExample::OnExtractionComplete(bool bSuccess, TArray<FString> ExtractedFiles)
{
    CurrentTask = nullptr; // Clear task reference

    if (bSuccess)
    {
        UE_LOG(LogTemp, Log, TEXT("Extraction completed successfully"));
        for (const FString& File : ExtractedFiles)
        {
            UE_LOG(LogTemp, Log, TEXT("Extracted file: %s"), *File);
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Extraction failed"));
    }
}

Advanced Asset Import System

Click to see the code
UCLASS()
class YOURGAME_API UAssetImportManager : public UObject
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable)
    bool ImportSpecificAsset(const FString& ArchivePath, const FString& AssetName, const FString& ImportName);

    UFUNCTION(BlueprintCallable)
    void CancelCurrentImport();

private:
    UFUNCTION()
    void OnImportProgress(float Progress);
    
    UFUNCTION()
    void OnImportComplete(bool bSuccess, TArray<FString> ExtractedFiles); // Fixed: Added <FString>
    
    UPROPERTY()
    FString CurrentImportName;
    
    UPROPERTY()
    UZipTask* CurrentTask; // Added: Track current task
};

bool UAssetImportManager::ImportSpecificAsset(const FString& ArchivePath, const FString& AssetName, const FString& ImportName)
{
    // Validate inputs
    if (ArchivePath.IsEmpty() || AssetName.IsEmpty() || ImportName.IsEmpty())
    {
        UE_LOG(LogTemp, Error, TEXT("Invalid parameters for asset import"));
        return false;
    }

    // Check if already importing
    if (CurrentTask)
    {
        UE_LOG(LogTemp, Warning, TEXT("Import already in progress, cancelling previous task"));
        CancelCurrentImport();
    }

    // Validate archive exists
    if (!FPaths::FileExists(ArchivePath))
    {
        UE_LOG(LogTemp, Error, TEXT("Archive not found: %s"), *ArchivePath);
        return false;
    }

    CurrentImportName = ImportName;
    
    FZipProgressDelegate ProgressDelegate;
    ProgressDelegate.BindUFunction(this, FName("OnImportProgress"));
    
    FUnzipTaskCompleteDelegate CompleteDelegate;
    CompleteDelegate.BindUFunction(this, FName("OnImportComplete"));
    
    CurrentTask = UArchiveManagerBPLibrary::UnzipAsyncWithRename(
        ArchivePath,
        AssetName,
        false,
        ImportName,
        ProgressDelegate,
        CompleteDelegate
    );

    if (CurrentTask)
    {
        UE_LOG(LogTemp, Log, TEXT("Started importing asset '%s' as '%s'"), *AssetName, *ImportName);
        return true;
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to start asset import task"));
        CurrentImportName.Empty();
        return false;
    }
}

void UAssetImportManager::CancelCurrentImport()
{
    if (CurrentTask)
    {
        UArchiveManagerBPLibrary::Cancel(); // Cancel current operation
        CurrentTask = nullptr;
        CurrentImportName.Empty();
        UE_LOG(LogTemp, Log, TEXT("Import operation cancelled"));
    }
}

void UAssetImportManager::OnImportProgress(float Progress)
{
    UE_LOG(LogTemp, VeryVerbose, TEXT("Import progress for '%s': %.1f%%"), *CurrentImportName, Progress * 100.0f);
}

void UAssetImportManager::OnImportComplete(bool bSuccess, TArray<FString> ExtractedFiles)
{
    CurrentTask = nullptr; // Clear task reference

    if (bSuccess)
    {
        UE_LOG(LogTemp, Log, TEXT("Successfully imported asset as '%s'"), *CurrentImportName);
        
        for (const FString& File : ExtractedFiles)
        {
            UE_LOG(LogTemp, Log, TEXT("Extracted file: %s"), *File);
            
            // Additional processing could be done here:
            // - Load the asset into Unreal Engine
            // - Validate file integrity
            // - Update asset registry
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to import asset '%s'"), *CurrentImportName);
    }

    CurrentImportName.Empty();
}

Save Game Recovery System

Click to see the code
UCLASS()
class YOURGAME_API UGameSaveManager : public UObject
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable)
    bool RecoverSpecificSave(const FString& BackupArchive, const FString& SaveFileName);

private:
    UFUNCTION()
    void OnRecoveryProgress(float Progress);
    
    UFUNCTION()
    void OnRecoveryComplete(bool bSuccess, TArray<FString> ExtractedFiles);
    
    UPROPERTY()
    UZipTask* RecoveryTask;
    
    UPROPERTY()
    FString RecoveryTargetName;
};

bool UGameSaveManager::RecoverSpecificSave(const FString& BackupArchive, const FString& SaveFileName)
{
    // Validate inputs
    if (BackupArchive.IsEmpty() || SaveFileName.IsEmpty())
    {
        UE_LOG(LogTemp, Error, TEXT("Invalid parameters for save recovery"));
        return false;
    }

    // Check if archive exists
    if (!FPaths::FileExists(BackupArchive))
    {
        UE_LOG(LogTemp, Error, TEXT("Backup archive not found: %s"), *BackupArchive);
        return false;
    }

    // Cancel any existing recovery
    if (RecoveryTask)
    {
        UE_LOG(LogTemp, Warning, TEXT("Previous recovery in progress, cancelling"));
        UArchiveManagerBPLibrary::Cancel();
        RecoveryTask = nullptr;
    }

    // Generate unique recovery filename
    FString Timestamp = FDateTime::Now().ToString(TEXT("%Y%m%d_%H%M%S"));
    RecoveryTargetName = FString::Printf(TEXT("recovered_%s_%s.sav"), 
        *SaveFileName, 
        *Timestamp);
    
    FZipProgressDelegate ProgressDelegate;
    ProgressDelegate.BindUFunction(this, FName("OnRecoveryProgress"));
    
    FUnzipTaskCompleteDelegate CompleteDelegate;
    CompleteDelegate.BindUFunction(this, FName("OnRecoveryComplete"));
    
    RecoveryTask = UArchiveManagerBPLibrary::UnzipAsyncWithRename(
        BackupArchive,
        SaveFileName,
        false,
        RecoveryTargetName,
        ProgressDelegate,
        CompleteDelegate
    );

    if (RecoveryTask)
    {
        UE_LOG(LogTemp, Log, TEXT("Started save recovery: %s -> %s"), *SaveFileName, *RecoveryTargetName);
        return true;
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to start save recovery task"));
        RecoveryTargetName.Empty();
        return false;
    }
}

void UGameSaveManager::OnRecoveryProgress(float Progress)
{
    UE_LOG(LogTemp, Log, TEXT("Save recovery progress: %.1f%%"), Progress * 100.0f);
}

void UGameSaveManager::OnRecoveryComplete(bool bSuccess, TArray<FString> ExtractedFiles)
{
    RecoveryTask = nullptr; // Clear task reference

    if (bSuccess && ExtractedFiles.Num() > 0)
    {
        UE_LOG(LogTemp, Log, TEXT("Save recovery successful: %s"), *ExtractedFiles[0]);
        
        // Additional recovery validation could be done here:
        // - Verify save file integrity
        // - Load and validate save data
        // - Backup original save before replacing
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Save recovery failed for: %s"), *RecoveryTargetName);
    }

    RecoveryTargetName.Empty();
}

Async Utility Function with Callback Handling

Click to see the code
namespace UFileExtractionUtils
{
    // Fixed version with proper async handling
    void ExtractSpecificFileWithTimestamp(
        const FString& ZipPath, 
        const FString& SourceFile, 
        const FString& FilePrefix,
        TFunction<void(bool, const FString&)> OnComplete) // Added callback parameter
    {
        // Input validation
        if (ZipPath.IsEmpty() || SourceFile.IsEmpty() || FilePrefix.IsEmpty())
        {
            UE_LOG(LogTemp, Error, TEXT("Invalid parameters for file extraction"));
            if (OnComplete) OnComplete(false, FString());
            return;
        }

        // Validate zip file exists
        if (!FPaths::FileExists(ZipPath))
        {
            UE_LOG(LogTemp, Error, TEXT("Zip file not found: %s"), *ZipPath);
            if (OnComplete) OnComplete(false, FString());
            return;
        }

        // Generate timestamp filename
        FString Timestamp = FDateTime::Now().ToString(TEXT("%Y%m%d_%H%M%S"));
        FString NewFileName = FString::Printf(TEXT("%s_%s.dat"), *FilePrefix, *Timestamp);
        
        // Setup delegates with proper binding
        FZipProgressDelegate ProgressDelegate;
        ProgressDelegate.BindLambda([NewFileName](float Progress)
        {
            UE_LOG(LogTemp, VeryVerbose, TEXT("Extracting %s: %.1f%%"), *NewFileName, Progress * 100.0f);
        });
        
        FUnzipTaskCompleteDelegate CompleteDelegate;
        CompleteDelegate.BindLambda([OnComplete, NewFileName](bool bSuccess, TArray<FString> ExtractedFiles)
        {
            if (bSuccess && ExtractedFiles.Num() > 0)
            {
                UE_LOG(LogTemp, Log, TEXT("Successfully extracted as: %s"), *ExtractedFiles[0]);
                if (OnComplete) OnComplete(true, ExtractedFiles[0]);
            }
            else
            {
                UE_LOG(LogTemp, Error, TEXT("Failed to extract file as: %s"), *NewFileName);
                if (OnComplete) OnComplete(false, FString());
            }
        });
        
        // Start extraction with task validation
        UZipTask* Task = UArchiveManagerBPLibrary::UnzipAsyncWithRename(
            ZipPath,
            SourceFile,
            false,
            NewFileName,
            ProgressDelegate,
            CompleteDelegate
        );

        if (!Task)
        {
            UE_LOG(LogTemp, Error, TEXT("Failed to create extraction task"));
            if (OnComplete) OnComplete(false, FString());
        }
        else
        {
            UE_LOG(LogTemp, Log, TEXT("Started extraction: %s -> %s"), *SourceFile, *NewFileName);
        }
    }

    // Usage example for the corrected utility function
    void ExampleUsage()
    {
        ExtractSpecificFileWithTimestamp(
            TEXT("C:/Archives/Data.zip"),
            TEXT("config.json"),
            TEXT("backup_config"),
            [](bool bSuccess, const FString& ExtractedPath)
            {
                if (bSuccess)
                {
                    UE_LOG(LogTemp, Log, TEXT("File successfully extracted to: %s"), *ExtractedPath);
                    // Process the extracted file here
                }
                else
                {
                    UE_LOG(LogTemp, Error, TEXT("Extraction failed"));
                }
            }
        );
    }
}

Advanced Features

Predictable File Selection

The Source Filename parameter allows you to:

  • Target specific files: Extract exactly the file you need by name
  • Navigate subdirectories: Use paths like “config/settings.json”
  • Handle case sensitivity: Match exact filenames as stored in archive

Automatic File Renaming

The Extracted Data Filename parameter allows you to:

  • Standardize naming: Convert random filenames to project conventions
  • Add timestamps: Create unique filenames for each extraction
  • Change extensions: Modify file format designation during extraction
  • Add prefixes/suffixes: Organize files with consistent naming patterns

Specific File Focus

This function is optimized for scenarios where you need a particular file:

  • Configuration loading: Extract specific config file from bundle
  • Asset importing: Extract particular asset file from package
  • Save game recovery: Extract specific save file from backup
  • Template extraction: Get specific template file from package

Progress Tracking for Targeted Files

Even for specific file extraction, progress tracking is valuable for:

  • Large file extraction (videos, high-res textures, models)
  • User feedback during import operations
  • Timeout detection for corrupted archives
  • Cancellation support for responsive UI

Common Use Cases

Game Development

  • Asset Pipeline: Import specific assets from artist packages
  • DLC Loading: Extract particular content file from DLC package
  • Save Recovery: Restore specific save file from backup
  • Texture Import: Extract particular high-resolution texture from package

Application Development

  • Document Import: Extract specific document from archive
  • Configuration Deploy: Extract particular config file with environment-specific naming
  • Template Installation: Extract specific template with project naming
  • Data Recovery: Restore particular data file from backup

Best Practices

Filename Strategy

  • Use exact names: Source filename must match exactly (case-sensitive)
  • Include paths: Use “subfolder/file.txt” for files in subdirectories
  • Descriptive output names: Include purpose, timestamp, or version in extracted filename
  • Follow conventions: Use project-specific naming standards
  • Avoid conflicts: Include unique identifiers to prevent overwrites

Error Handling

  • Validate source file: Ensure the specific file exists in archive
  • Check filename validity: Ensure extracted filename is valid for filesystem
  • Handle extraction failures: Provide meaningful error messages
  • Verify extracted file: Validate extracted file integrity

Performance Considerations

  • Ideal for specific assets: Perfect when you know exactly which file you need
  • Efficient extraction: Only processes the target file, ignores rest of archive
  • Memory efficient: Doesn’t load entire archive into memory
  • Quick operation: Faster than extracting all files when only one is needed

Extraction Behavior

  • File Selection: Extracts the specifically named file from the ZIP archive
  • Error on missing: Fails with clear error if source file not found
  • Renaming: File is renamed during extraction process, not after
  • Location: Extracted to same directory as source ZIP file
  • Original Preservation: Original filename is replaced with new name
  • Metadata: File timestamps and attributes are preserved

Common Errors

“Specified source file not found”

  • Cause: The filename doesn’t match any file in the archive
  • Solution: Check exact spelling and path of the file in the archive

“Failed opening zip archive”

  • Cause: Zip file doesn’t exist or is corrupted
  • Solution: Verify the zip file path and integrity

“Permission denied”

  • Cause: Insufficient permissions to write to extraction location
  • Solution: Check write permissions for the target directory
Table of Contents