From f2c241c3239657d46431ff1a7cf747a54cf4a2c7 Mon Sep 17 00:00:00 2001 From: zarzet Date: Thu, 8 Jan 2026 00:26:49 +0700 Subject: [PATCH] Fix .tmp permission issue on Android Music folder --- CHANGELOG.md | 2 -- go_backend/amazon.go | 18 +++++------------- go_backend/exports.go | 5 +++++ go_backend/qobuz.go | 18 +++++------------- go_backend/tidal.go | 34 +++++++++------------------------- 5 files changed, 24 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c22a84f6..347d3b40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,10 +20,8 @@ - Progress now updates smoothly every 64KB of data received - First progress update happens immediately when download starts - **Incomplete Downloads**: Fixed bug where interrupted downloads could result in corrupted/incomplete files - - Downloads now use temporary files (`.tmp`) during transfer - File size is validated against server's Content-Length header - Incomplete files are automatically deleted and error is reported - - Final file is only created after successful download completion - Applies to all services: Tidal, Qobuz, and Amazon ### Technical diff --git a/go_backend/amazon.go b/go_backend/amazon.go index bd5619f7..4455a9ca 100644 --- a/go_backend/amazon.go +++ b/go_backend/amazon.go @@ -300,9 +300,7 @@ func (a *AmazonDownloader) DownloadFile(downloadURL, outputPath, itemID string) SetItemBytesTotal(itemID, expectedSize) } - // Use temp file to avoid incomplete downloads - tempPath := outputPath + ".tmp" - out, err := os.Create(tempPath) + out, err := os.Create(outputPath) if err != nil { return err } @@ -326,30 +324,24 @@ func (a *AmazonDownloader) DownloadFile(downloadURL, outputPath, itemID string) // Check for any errors if err != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("download interrupted: %w", err) } if flushErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to flush buffer: %w", flushErr) } if closeErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to close file: %w", closeErr) } // Verify file size if Content-Length was provided if expectedSize > 0 && written != expectedSize { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("incomplete download: expected %d bytes, got %d bytes", expectedSize, written) } - // Rename temp file to final path - if err := os.Rename(tempPath, outputPath); err != nil { - os.Remove(tempPath) - return fmt.Errorf("failed to rename temp file: %w", err) - } - fmt.Printf("\r[Amazon] Downloaded: %.2f MB (Complete)\n", float64(written)/(1024*1024)) return nil } diff --git a/go_backend/exports.go b/go_backend/exports.go index 1a22f180..94c8a69b 100644 --- a/go_backend/exports.go +++ b/go_backend/exports.go @@ -282,6 +282,8 @@ func DownloadWithFallback(requestJSON string) (string, error) { preferredService = "tidal" } + fmt.Printf("[DownloadWithFallback] Preferred service from request: '%s'\n", req.Service) + // Create ordered list: preferred first, then others services := []string{preferredService} for _, s := range allServices { @@ -290,9 +292,12 @@ func DownloadWithFallback(requestJSON string) (string, error) { } } + fmt.Printf("[DownloadWithFallback] Service order: %v\n", services) + var lastErr error for _, service := range services { + fmt.Printf("[DownloadWithFallback] Trying service: %s\n", service) req.Service = service var result DownloadResult diff --git a/go_backend/qobuz.go b/go_backend/qobuz.go index 023ff72c..a5c1d0bf 100644 --- a/go_backend/qobuz.go +++ b/go_backend/qobuz.go @@ -479,9 +479,7 @@ func (q *QobuzDownloader) DownloadFile(downloadURL, outputPath, itemID string) e SetItemBytesTotal(itemID, expectedSize) } - // Use temp file to avoid incomplete downloads - tempPath := outputPath + ".tmp" - out, err := os.Create(tempPath) + out, err := os.Create(outputPath) if err != nil { return err } @@ -505,30 +503,24 @@ func (q *QobuzDownloader) DownloadFile(downloadURL, outputPath, itemID string) e // Check for any errors if err != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("download interrupted: %w", err) } if flushErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to flush buffer: %w", flushErr) } if closeErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to close file: %w", closeErr) } // Verify file size if Content-Length was provided if expectedSize > 0 && written != expectedSize { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("incomplete download: expected %d bytes, got %d bytes", expectedSize, written) } - // Rename temp file to final path - if err := os.Rename(tempPath, outputPath); err != nil { - os.Remove(tempPath) - return fmt.Errorf("failed to rename temp file: %w", err) - } - return nil } diff --git a/go_backend/tidal.go b/go_backend/tidal.go index 940bd6c7..bb8178fc 100644 --- a/go_backend/tidal.go +++ b/go_backend/tidal.go @@ -752,9 +752,7 @@ func (t *TidalDownloader) DownloadFile(downloadURL, outputPath, itemID string) e SetItemBytesTotal(itemID, expectedSize) } - // Use temp file to avoid incomplete downloads - tempPath := outputPath + ".tmp" - out, err := os.Create(tempPath) + out, err := os.Create(outputPath) if err != nil { return err } @@ -778,30 +776,24 @@ func (t *TidalDownloader) DownloadFile(downloadURL, outputPath, itemID string) e // Check for any errors if err != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("download interrupted: %w", err) } if flushErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to flush buffer: %w", flushErr) } if closeErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to close file: %w", closeErr) } // Verify file size if Content-Length was provided if expectedSize > 0 && written != expectedSize { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("incomplete download: expected %d bytes, got %d bytes", expectedSize, written) } - // Rename temp file to final path - if err := os.Rename(tempPath, outputPath); err != nil { - os.Remove(tempPath) - return fmt.Errorf("failed to rename temp file: %w", err) - } - return nil } @@ -844,9 +836,7 @@ func (t *TidalDownloader) downloadFromManifest(manifestB64, outputPath, itemID s SetItemBytesTotal(itemID, expectedSize) } - // Use temp file to avoid incomplete downloads - tempPath := outputPath + ".tmp" - out, err := os.Create(tempPath) + out, err := os.Create(outputPath) if err != nil { return fmt.Errorf("failed to create file: %w", err) } @@ -863,26 +853,20 @@ func (t *TidalDownloader) downloadFromManifest(manifestB64, outputPath, itemID s closeErr := out.Close() if err != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("download interrupted: %w", err) } if closeErr != nil { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("failed to close file: %w", closeErr) } // Verify file size if Content-Length was provided if expectedSize > 0 && written != expectedSize { - os.Remove(tempPath) + os.Remove(outputPath) return fmt.Errorf("incomplete download: expected %d bytes, got %d bytes", expectedSize, written) } - // Rename temp file to final path - if err := os.Rename(tempPath, outputPath); err != nil { - os.Remove(tempPath) - return fmt.Errorf("failed to rename temp file: %w", err) - } - return nil }