Skip to content

Commit d92b3db

Browse files
add: remotefs/Download function to support file download
Signed-off-by: Michael Kaplan <[email protected]>
1 parent d22ade8 commit d92b3db

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

remotefs/download.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package remotefs
2+
3+
import (
4+
"crypto/sha256"
5+
"encoding/hex"
6+
"fmt"
7+
"io"
8+
"os"
9+
)
10+
11+
// ErrChecksumMismatch is returned when the checksum of the uploaded file does not match the local checksum.
12+
13+
// Download a file from the remote host.
14+
func Download(fs FS, src, dst string) error {
15+
remote, err := fs.Open(src)
16+
if err != nil {
17+
return fmt.Errorf("open remote file for download: %w", err)
18+
}
19+
defer remote.Close()
20+
21+
remoteStat, err := remote.Stat()
22+
if err != nil {
23+
return fmt.Errorf("stat remote file for download: %w", err)
24+
}
25+
26+
remoteSum := sha256.New()
27+
localSum := sha256.New()
28+
29+
local, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, remoteStat.Mode())
30+
if err != nil {
31+
return fmt.Errorf("open local file for download: %w", err)
32+
}
33+
defer local.Close()
34+
35+
remoteReader := io.TeeReader(remote, remoteSum)
36+
if _, err := io.Copy(io.MultiWriter(local, localSum), remoteReader); err != nil {
37+
_ = local.Close()
38+
return fmt.Errorf("copy file from remote host: %w", err)
39+
}
40+
if err := local.Close(); err != nil {
41+
return fmt.Errorf("close local file after download: %w", err)
42+
}
43+
44+
ls := hex.EncodeToString(localSum.Sum(nil))
45+
rs := hex.EncodeToString(remoteSum.Sum(nil))
46+
if ls != rs {
47+
return ErrChecksumMismatch
48+
}
49+
50+
return nil
51+
}

0 commit comments

Comments
 (0)