Fix delete endpoint to work with kept folder and clean up empty directories

- Changed delete endpoint from Library:DownloadPath to /app/kept
- Now properly deletes empty Album and Artist folders after file deletion
- Added debug logging for deletion operations
- Structure: Artist/Album/Track.flac
This commit is contained in:
2026-02-07 00:32:22 -05:00
parent 3a9d00dcdb
commit c9b44dea43

View File

@@ -3402,7 +3402,7 @@ public class LinkPlaylistRequest
/// <summary> /// <summary>
/// DELETE /api/admin/downloads /// DELETE /api/admin/downloads
/// Deletes a specific downloaded file /// Deletes a specific kept file and cleans up empty folders
/// </summary> /// </summary>
[HttpDelete("downloads")] [HttpDelete("downloads")]
public IActionResult DeleteDownload([FromQuery] string path) public IActionResult DeleteDownload([FromQuery] string path)
@@ -3414,47 +3414,52 @@ public class LinkPlaylistRequest
return BadRequest(new { error = "Path is required" }); return BadRequest(new { error = "Path is required" });
} }
var downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads"; var keptPath = "/app/kept";
var fullPath = Path.Combine(downloadPath, path); var fullPath = Path.Combine(keptPath, path);
// Security: Ensure the path is within the download directory _logger.LogInformation("🗑️ Delete request for: {Path}", fullPath);
// Security: Ensure the path is within the kept directory
var normalizedFullPath = Path.GetFullPath(fullPath); var normalizedFullPath = Path.GetFullPath(fullPath);
var normalizedDownloadPath = Path.GetFullPath(downloadPath); var normalizedKeptPath = Path.GetFullPath(keptPath);
if (!normalizedFullPath.StartsWith(normalizedDownloadPath)) if (!normalizedFullPath.StartsWith(normalizedKeptPath))
{ {
_logger.LogWarning("🗑️ Invalid path (outside kept folder): {Path}", normalizedFullPath);
return BadRequest(new { error = "Invalid path" }); return BadRequest(new { error = "Invalid path" });
} }
if (!System.IO.File.Exists(fullPath)) if (!System.IO.File.Exists(fullPath))
{ {
_logger.LogWarning("🗑️ File not found: {Path}", fullPath);
return NotFound(new { error = "File not found" }); return NotFound(new { error = "File not found" });
} }
System.IO.File.Delete(fullPath); System.IO.File.Delete(fullPath);
_logger.LogInformation("Deleted download: {Path}", path); _logger.LogInformation("🗑️ Deleted file: {Path}", fullPath);
// Clean up empty directories // Clean up empty directories (Album folder, then Artist folder if empty)
var directory = Path.GetDirectoryName(fullPath); var directory = Path.GetDirectoryName(fullPath);
while (directory != null && directory != downloadPath) while (directory != null && directory != keptPath && directory.StartsWith(keptPath))
{ {
if (Directory.Exists(directory) && !Directory.EnumerateFileSystemEntries(directory).Any()) if (Directory.Exists(directory) && !Directory.EnumerateFileSystemEntries(directory).Any())
{ {
Directory.Delete(directory); Directory.Delete(directory);
_logger.LogDebug("Deleted empty directory: {Dir}", directory); _logger.LogInformation("🗑️ Deleted empty directory: {Dir}", directory);
directory = Path.GetDirectoryName(directory);
} }
else else
{ {
_logger.LogDebug("🗑️ Directory not empty or doesn't exist, stopping cleanup: {Dir}", directory);
break; break;
} }
directory = Path.GetDirectoryName(directory);
} }
return Ok(new { success = true, message = "File deleted successfully" }); return Ok(new { success = true, message = "File deleted successfully" });
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to delete download: {Path}", path); _logger.LogError(ex, "Failed to delete file: {Path}", path);
return StatusCode(500, new { error = "Failed to delete file" }); return StatusCode(500, new { error = "Failed to delete file" });
} }
} }