From f7621b2c6c96a245112ed748637c95a5434357a3 Mon Sep 17 00:00:00 2001 From: l Date: Sun, 24 Dec 2023 19:39:33 +0100 Subject: [PATCH] feat: partial download (#1486) * add .partial download * fix Stat check * review partial download --- pkg/utils/uri.go | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/pkg/utils/uri.go b/pkg/utils/uri.go index 8046b89f..260e65a9 100644 --- a/pkg/utils/uri.go +++ b/pkg/utils/uri.go @@ -94,6 +94,20 @@ func ConvertURL(s string) string { return s } +func removePartialFile(tmpFilePath string) error { + _, err := os.Stat(tmpFilePath) + if err == nil { + log.Debug().Msgf("Removing temporary file %s", tmpFilePath) + err = os.Remove(tmpFilePath) + if err != nil { + err1 := fmt.Errorf("failed to remove temporary download file %s: %v", tmpFilePath, err) + log.Warn().Msg(err1.Error()) + return err1 + } + } + return nil +} + func DownloadFile(url string, filePath, sha string, downloadStatus func(string, string, string, float64)) error { url = ConvertURL(url) // Check if the file already exists @@ -143,15 +157,24 @@ func DownloadFile(url string, filePath, sha string, downloadStatus func(string, return fmt.Errorf("failed to create parent directory for file %q: %v", filePath, err) } - // Create and write file content - outFile, err := os.Create(filePath) + // save partial download to dedicated file + tmpFilePath := filePath + ".partial" + + // remove tmp file + err = removePartialFile(tmpFilePath) if err != nil { - return fmt.Errorf("failed to create file %q: %v", filePath, err) + return err + } + + // Create and write file content + outFile, err := os.Create(tmpFilePath) + if err != nil { + return fmt.Errorf("failed to create file %q: %v", tmpFilePath, err) } defer outFile.Close() progress := &progressWriter{ - fileName: filePath, + fileName: tmpFilePath, total: resp.ContentLength, hash: sha256.New(), downloadStatus: downloadStatus, @@ -161,6 +184,11 @@ func DownloadFile(url string, filePath, sha string, downloadStatus func(string, return fmt.Errorf("failed to write file %q: %v", filePath, err) } + err = os.Rename(tmpFilePath, filePath) + if err != nil { + return fmt.Errorf("failed to rename temporary file %s -> %s: %v", tmpFilePath, filePath, err) + } + if sha != "" { // Verify SHA calculatedSHA := fmt.Sprintf("%x", progress.hash.Sum(nil))