diff --git a/Intersect.Editor/Forms/FrmUploadToServer.cs b/Intersect.Editor/Forms/FrmUploadToServer.cs index a42403feb2..ee76f59cb3 100644 --- a/Intersect.Editor/Forms/FrmUploadToServer.cs +++ b/Intersect.Editor/Forms/FrmUploadToServer.cs @@ -25,6 +25,13 @@ public FrmUploadToServer() InitializeComponent(); Icon = Program.Icon; LoadSettings(); + FormClosing += FrmUploadToServer_FormClosing; + } + + private void FrmUploadToServer_FormClosing(object? sender, FormClosingEventArgs e) + { + // Save settings when form is closing + SaveSettings(); } private void LoadSettings() @@ -44,6 +51,14 @@ private void LoadSettings() rbEditorAssets.Checked = savedType == "editor"; rbClientAssets.Checked = !rbEditorAssets.Checked; + var savedDirectory = Preferences.LoadPreference("upload_lastDirectory"); + if (!string.IsNullOrWhiteSpace(savedDirectory) && Directory.Exists(savedDirectory)) + { + _selectedDirectory = savedDirectory; + txtDirectory.Text = savedDirectory; + btnUpload.Enabled = true; + } + var rawTokenResponse = Preferences.LoadPreference(nameof(TokenResponse)); if (!string.IsNullOrWhiteSpace(rawTokenResponse)) { @@ -56,6 +71,20 @@ private void LoadSettings() _tokenResponse = null; } } + + UpdateAuthenticationStatus(); + } + + private void UpdateAuthenticationStatus() + { + if (_tokenResponse != null) + { + lblStatus.Text = "✓ Authenticated"; + } + else + { + lblStatus.Text = "⚠ Not authenticated - login through the editor first"; + } } private void SaveSettings() @@ -184,9 +213,11 @@ private async Task PerformUpload() { var batch = files.Skip(i).Take(batchSize).ToArray(); var attempt = 0; + Exception? lastException = null; - while (true) + while (attempt <= maxRetries) { + var streams = new List(); try { using var content = new MultipartFormDataContent(); @@ -198,6 +229,7 @@ private async Task PerformUpload() .Replace('\\', '/'); var stream = File.OpenRead(filePath); + streams.Add(stream); var fileContent = new StreamContent(stream); fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream"); @@ -211,7 +243,7 @@ private async Task PerformUpload() System.Net.HttpStatusCode.Unauthorized) { throw new Exception( - "Authentication expired. Please log in again." + "Authentication required. Please ensure you have logged in with developer credentials." ); } @@ -235,13 +267,33 @@ private async Task PerformUpload() break; } - catch when (++attempt <= maxRetries) + catch (Exception ex) { - var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt)); - lblStatus.Text = - $"Retrying batch ({attempt}/{maxRetries})..."; - await Task.Delay(delay); + lastException = ex; + attempt++; + + if (attempt <= maxRetries) + { + var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt)); + lblStatus.Text = + $"Retrying batch ({attempt}/{maxRetries})..."; + await Task.Delay(delay); + } } + finally + { + // Ensure all streams are disposed + foreach (var stream in streams) + { + stream?.Dispose(); + } + } + } + + // If all retries failed, throw the last exception + if (lastException != null && attempt > maxRetries) + { + throw lastException; } } diff --git a/Intersect.Server/Web/Controllers/Api/EditorUpdatesController.cs b/Intersect.Server/Web/Controllers/Api/EditorUpdatesController.cs index 7f3797266d..b6f06a7d08 100644 --- a/Intersect.Server/Web/Controllers/Api/EditorUpdatesController.cs +++ b/Intersect.Server/Web/Controllers/Api/EditorUpdatesController.cs @@ -137,16 +137,18 @@ private async Task UploadFilesInternal( } // Create destination directory if it doesn't exist - var directoryInfo = new DirectoryInfo(destinationFolder); - if (!directoryInfo.Exists) + // Use Directory.CreateDirectory to create all parent directories + if (!Directory.Exists(destinationFolder)) { _logger.LogInformation( "Creating directory for updates: {DirectoryPath}", relativeDestinationFolder ); - directoryInfo.Create(); + Directory.CreateDirectory(destinationFolder); } + var directoryInfo = new DirectoryInfo(destinationFolder); + // Process each file var results = new Dictionary(); long totalBytesUploaded = 0;