Refactor downloads to use job-specific subdirectories
Organize downloaded files into per-job subdirectories under "downloads" instead of a flat structure. Update DownloadController and VideoService to read, write, and delete files within these job-specific directories. Add helper methods for directory management and improve logging. Update download/delete endpoints and result URLs to reflect the new structure. Clean up empty job directories after file deletion.
This commit is contained in:
+54
-10
@@ -1,7 +1,10 @@
|
||||
@page "/"
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using TuneRipper.Shared.Models
|
||||
@using TuneRipper.Services
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject ITuneRipperApiService ApiService
|
||||
@inject IClientSessionService SessionService
|
||||
@inject ILogger<Home> Logger
|
||||
|
||||
<PageTitle>TuneRipper - YouTube to MP3 Downloader</PageTitle>
|
||||
@@ -25,6 +28,14 @@
|
||||
<img src="images/logo.png" alt="TuneRipper Logo" class="logo" />
|
||||
<h1 class="app-title">TuneRipper</h1>
|
||||
<p class="app-subtitle">Convert YouTube videos to MP3 instantly</p>
|
||||
|
||||
@* Session info display *@
|
||||
@if (!string.IsNullOrWhiteSpace(currentSessionId))
|
||||
{
|
||||
<div class="session-info">
|
||||
<small>Session: @currentSessionId.Substring(0, 8)...</small>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="download-form">
|
||||
@@ -161,6 +172,7 @@
|
||||
private string progressMessage = "";
|
||||
private List<DownloadItem> downloadLinks = new();
|
||||
private YouTubeVideoDetails? currentVideoDetails = null;
|
||||
private string currentSessionId = "";
|
||||
|
||||
public class DownloadItem
|
||||
{
|
||||
@@ -170,6 +182,22 @@
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Initialize session on component load
|
||||
currentSessionId = await SessionService.GetCurrentSessionIdAsync();
|
||||
Logger.LogInformation("Initialized with session: {SessionId}", currentSessionId);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error initializing session");
|
||||
// Don't block the UI if session initialization fails
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadMp3()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(youtubeUrl))
|
||||
@@ -182,6 +210,12 @@
|
||||
|
||||
try
|
||||
{
|
||||
// Ensure we have a session
|
||||
if (string.IsNullOrWhiteSpace(currentSessionId))
|
||||
{
|
||||
currentSessionId = await SessionService.GetCurrentSessionIdAsync();
|
||||
}
|
||||
|
||||
// Step 1: Start processing (which includes video details fetching)
|
||||
progressMessage = "Starting video processing...";
|
||||
progressPercentage = 5;
|
||||
@@ -191,7 +225,8 @@
|
||||
{
|
||||
Url = youtubeUrl,
|
||||
Format = "mp3",
|
||||
Quality = "128"
|
||||
Quality = "128",
|
||||
SessionId = currentSessionId // Include session ID in request
|
||||
};
|
||||
|
||||
var processingResponse = await ApiService.StartProcessingAsync(request);
|
||||
@@ -199,9 +234,18 @@
|
||||
if (processingResponse?.Success == true)
|
||||
{
|
||||
var jobId = processingResponse.FileName; // This contains the job ID
|
||||
var sessionId = processingResponse.SessionId ?? currentSessionId;
|
||||
|
||||
// Update current session ID if server returned a different one
|
||||
if (!string.IsNullOrWhiteSpace(processingResponse.SessionId) &&
|
||||
processingResponse.SessionId != currentSessionId)
|
||||
{
|
||||
currentSessionId = processingResponse.SessionId;
|
||||
await SessionService.SetSessionIdAsync(currentSessionId);
|
||||
}
|
||||
|
||||
// Step 2: Monitor processing status and get video details
|
||||
await MonitorProcessingAndShowDetails(jobId);
|
||||
await MonitorProcessingAndShowDetails(jobId, sessionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -221,7 +265,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task MonitorProcessingAndShowDetails(string jobId)
|
||||
private async Task MonitorProcessingAndShowDetails(string jobId, string sessionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -256,7 +300,7 @@
|
||||
var result = await ApiService.GetProcessingResultAsync(jobId);
|
||||
if (result?.Success == true)
|
||||
{
|
||||
await CompleteProcessing(result, jobId);
|
||||
await CompleteProcessing(result, jobId, sessionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -295,7 +339,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CompleteProcessing(ProcessVideoResponse result, string jobId)
|
||||
private async Task CompleteProcessing(ProcessVideoResponse result, string jobId, string sessionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -308,17 +352,17 @@
|
||||
// Use the actual video title from API
|
||||
string title = currentVideoDetails?.Title ?? result.VideoDetails?.Title ?? ExtractTitleFromUrl(youtubeUrl);
|
||||
|
||||
// Create the download URL - either from the result or construct it from the job ID
|
||||
// Create the session-aware download URL
|
||||
string downloadUrl;
|
||||
if (!string.IsNullOrEmpty(result.DownloadUrl))
|
||||
if (!string.IsNullOrEmpty(result.DownloadUrl) && result.DownloadUrl.Contains(sessionId))
|
||||
{
|
||||
// If the result contains a direct download URL, use it
|
||||
// Server provided a session-aware download URL
|
||||
downloadUrl = result.DownloadUrl.StartsWith("http") ? result.DownloadUrl : $"https://localhost:7160{result.DownloadUrl}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: construct download URL from job ID
|
||||
downloadUrl = $"https://localhost:7160/api/download/{jobId}";
|
||||
// Construct session-aware download URL
|
||||
downloadUrl = $"https://localhost:7160/api/download/{sessionId}/{jobId}";
|
||||
}
|
||||
|
||||
downloadLinks.Add(new DownloadItem
|
||||
|
||||
Reference in New Issue
Block a user