How Can We Help?
   			
		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
| Parameter | Type | Description | 
|---|---|---|
| Path to Zip | String | Full absolute path to the ZIP file you want to extract from | 
| Source Filename | String | Exact name of the file to extract from the archive (e.g., “config.json”, “subfolder/data.txt”) | 
| Delete After Extraction | Boolean | If true, deletes the ZIP file after successful extraction | 
| Extracted Data Filename | String | New filename for the extracted file (e.g., “new_asset_file_name.psd”) | 
| Get Progress | Zip Progress Delegate | Callback function that receives progress updates (0.0 to 1.0) | 
| Callback | Unzip Task Complete Delegate | Callback function executed when extraction completes | 
Output Parameters
| Parameter | Type | Description | 
|---|---|---|
| Return Value | Zip Task | Reference 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::CancelCurrentOperation(); // 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
