From de78d31775f27ce6bfb51d7b2f96cde34792b5b1 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Mon, 29 Apr 2024 08:22:55 +0200 Subject: [PATCH] add: remotefs/download support file download --- remotefs/download.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 remotefs/download.go diff --git a/remotefs/download.go b/remotefs/download.go new file mode 100644 index 00000000..d2535b44 --- /dev/null +++ b/remotefs/download.go @@ -0,0 +1,53 @@ +package remotefs + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "os" +) + +// ErrChecksumMismatch is returned when the checksum of the uploaded file does not match the local checksum. +//var ErrChecksumMismatch = errors.New("checksum mismatch") + +// Download a file from the remote host. +func Download(fs FS, src, dst string) error { + remote, err := fs.Open(src) + if err != nil { + return fmt.Errorf("open remote file for download: %w", err) + } + defer remote.Close() + + remoteStat, err := remote.Stat() + if err != nil { + return fmt.Errorf("stat remote file for download: %w", err) + } + + remoteSum := sha256.New() + localSum := sha256.New() + + local, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, remoteStat.Mode()) + if err != nil { + return fmt.Errorf("open local file for download: %w", err) + } + defer local.Close() + + remoteReader := io.TeeReader(remote, remoteSum) + if _, err := io.Copy(io.MultiWriter(local, localSum), remoteReader); err != nil { + _ = local.Close() + return fmt.Errorf("copy file from remote host: %w", err) + } + if err := local.Close(); err != nil { + return fmt.Errorf("close local file after download: %w", err) + } + + ls := hex.EncodeToString(localSum.Sum(nil)) + rs := hex.EncodeToString(remoteSum.Sum(nil)) + fmt.Printf("local %s remote %s", ls, rs) + if ls != rs { + return ErrChecksumMismatch + } + + return nil +}