@using Data_Coupler.Services @using Data_Coupler.Models @inject IBackupService BackupService @inject IJSRuntime JSRuntime @inject ILogger Logger

Backup e Ripristino Dati

Gestisci il backup e il ripristino di profili, credenziali, associazioni e schedule. I backup non includono password o API keys per motivi di sicurezza.

Esporta Backup

Crea un backup completo del sistema con tutti i dati configurati.

@if (lastExportResult != null) {
@(lastExportResult.Success ? "Successo" : "Errore"):
@lastExportResult.Message
@if (lastExportResult.Success) { Durata: @lastExportResult.Duration.TotalSeconds.ToString("F1")s | Record: @(lastExportResult.ProcessedCounts.Profiles + lastExportResult.ProcessedCounts.Credentials + lastExportResult.ProcessedCounts.KeyAssociations + lastExportResult.ProcessedCounts.ProfileSchedules) }
}
Importa Backup

Ripristina i dati da un file di backup precedentemente creato.

Seleziona un file .json di backup di Data Coupler
@if (selectedBackupInfo != null) {
Informazioni Backup
Versione: @selectedBackupInfo.Metadata.Version
Creato: @selectedBackupInfo.Metadata.CreatedAt.ToString("dd/MM/yyyy HH:mm")
@if (!string.IsNullOrEmpty(selectedBackupInfo.Metadata.CreatedBy)) { Da: @selectedBackupInfo.Metadata.CreatedBy
}
Profili: @selectedBackupInfo.Profiles.Count
Credenziali: @selectedBackupInfo.Credentials.Count
Associazioni: @selectedBackupInfo.KeyAssociations.Count
Schedule: @selectedBackupInfo.ProfileSchedules.Count
@if (!string.IsNullOrEmpty(selectedBackupInfo.Metadata.Description)) {
Descrizione: @selectedBackupInfo.Metadata.Description
}
} @if (lastImportResult != null) {
@(lastImportResult.Success ? "Successo" : "Errore"):
@lastImportResult.Message
@if (lastImportResult.Success) { Durata: @lastImportResult.Duration.TotalSeconds.ToString("F1")s | Record importati: @(lastImportResult.ProcessedCounts.Profiles + lastImportResult.ProcessedCounts.Credentials + lastImportResult.ProcessedCounts.KeyAssociations + lastImportResult.ProcessedCounts.ProfileSchedules) } @if (lastImportResult.Warnings.Any()) {
Avvisi:
    @foreach (var warning in lastImportResult.Warnings) {
  • @warning
  • }
}
}
Backup Recenti

Elenco dei file di backup nella cartella Documenti/DataCoupler/Backups

@if (recentBackups.Any()) {
@foreach (var backup in recentBackups.Take(10)) { }
Nome File Data Creazione Dimensione Azioni
@backup.Name @backup.CreationTime.ToString("dd/MM/yyyy HH:mm") @FormatFileSize(backup.Length)
} else {

Nessun backup trovato

}
@code { [Parameter] public EventCallback<(string message, string type)> OnShowToast { get; set; } private BackupOptions exportOptions = new() { IncludeProfiles = true, IncludeCredentials = true, IncludeKeyAssociations = true, IncludeProfileSchedules = true, IncludeOnlyActiveRecords = true }; private RestoreOptions restoreOptions = new() { RestoreProfiles = true, RestoreCredentials = false, // Default false per sicurezza RestoreKeyAssociations = true, RestoreProfileSchedules = true, OverwriteExisting = false, CreateBackupBeforeRestore = true }; private bool isExporting = false; private bool isImporting = false; private BackupOperationResult? lastExportResult; private BackupOperationResult? lastImportResult; private SystemBackupData? selectedBackupInfo; private List recentBackups = new(); protected override async Task OnInitializedAsync() { await RefreshBackupList(); } private async Task ExportBackup() { try { isExporting = true; lastExportResult = null; StateHasChanged(); lastExportResult = await BackupService.ExportBackupAsync(exportOptions); if (lastExportResult.Success) { await OnShowToast.InvokeAsync(($"Backup creato con successo", "success")); await RefreshBackupList(); } else { await OnShowToast.InvokeAsync(("Errore durante la creazione del backup", "error")); } } catch (Exception ex) { Logger.LogError(ex, "Errore esportazione backup"); await OnShowToast.InvokeAsync(($"Errore: {ex.Message}", "error")); } finally { isExporting = false; StateHasChanged(); } } private async Task OnFileSelected(InputFileChangeEventArgs e) { try { var file = e.File; if (file != null) { using var stream = file.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024); // 10MB max using var reader = new StreamReader(stream); var content = await reader.ReadToEndAsync(); selectedBackupInfo = await BackupService.GetBackupInfoAsync(content); StateHasChanged(); } } catch (Exception ex) { Logger.LogError(ex, "Errore lettura file backup"); await OnShowToast.InvokeAsync(($"Errore lettura file: {ex.Message}", "error")); } } private async Task ImportBackup() { try { isImporting = true; lastImportResult = null; StateHasChanged(); if (selectedBackupInfo != null) { // Serializza il backup selezionato per l'import var backupContent = System.Text.Json.JsonSerializer.Serialize(selectedBackupInfo); lastImportResult = await BackupService.ImportBackupFromJsonAsync(backupContent, restoreOptions); if (lastImportResult.Success) { await OnShowToast.InvokeAsync(("Backup importato con successo", "success")); } else { await OnShowToast.InvokeAsync(("Errore durante l'importazione", "error")); } } } catch (Exception ex) { Logger.LogError(ex, "Errore importazione backup"); await OnShowToast.InvokeAsync(($"Errore: {ex.Message}", "error")); } finally { isImporting = false; StateHasChanged(); } } private Task RefreshBackupList() { try { var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var backupFolder = Path.Combine(documentsPath, "DataCoupler", "Backups"); if (Directory.Exists(backupFolder)) { var files = new DirectoryInfo(backupFolder) .GetFiles("*.json") .OrderByDescending(f => f.CreationTime) .ToList(); recentBackups = files; } else { recentBackups = new List(); } StateHasChanged(); } catch (Exception ex) { Logger.LogWarning(ex, "Errore refresh lista backup"); } return Task.CompletedTask; } private async Task DownloadBackup(string filePath) { try { var fileName = Path.GetFileName(filePath); var bytes = await File.ReadAllBytesAsync(filePath); var stream = new MemoryStream(bytes); using var streamRef = new DotNetStreamReference(stream); await JSRuntime.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef); await OnShowToast.InvokeAsync(($"Download di {fileName} avviato", "info")); } catch (Exception ex) { Logger.LogError(ex, "Errore download backup"); await OnShowToast.InvokeAsync(($"Errore download: {ex.Message}", "error")); } } private string FormatFileSize(long bytes) { string[] sizes = { "B", "KB", "MB", "GB" }; double len = bytes; int order = 0; while (len >= 1024 && order < sizes.Length - 1) { order++; len = len / 1024; } return $"{len:0.##} {sizes[order]}"; } }