Skip to content

Commit 04d09a3

Browse files
committed
refactor(transfer data): use helper function
1 parent a87dae5 commit 04d09a3

File tree

6 files changed

+77
-70
lines changed

6 files changed

+77
-70
lines changed

client/client.go

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"encoding/binary"
77
"encoding/json"
88
"fmt"
9-
"io"
109
"net"
1110
"os"
1211
"path/filepath"
@@ -59,36 +58,18 @@ func receiveFile(conn net.Conn, file config.File, savePath string, fileID, progr
5958
}
6059
defer f.Close()
6160

62-
shortedFileName := utils.ShortedString(file.Name, 10, 6, 4)
63-
64-
buffer := make([]byte, config.DefaultChunkSize)
65-
var totalBytesRead, totalBytesWritten int64
66-
byteToRead := config.DefaultChunkSize
67-
68-
for totalBytesRead < file.Size {
69-
if config.DefaultChunkSize > file.Size-totalBytesRead {
70-
byteToRead = int(file.Size - totalBytesRead)
71-
}
72-
n, err := io.ReadFull(conn, buffer[:byteToRead])
73-
if err != nil {
74-
return fmt.Errorf("failed to read buffer from network, %v", err)
75-
}
76-
77-
m, err := f.Write(buffer[:n])
78-
if err != nil {
79-
return fmt.Errorf("failed to write buffer into file, %v", err)
80-
}
81-
82-
totalBytesRead += int64(n)
83-
if !silentTransfer {
84-
totalBytesWritten += int64(m)
85-
receivedPercent := int(totalBytesWritten * 100 / file.Size)
86-
utils.DrawProgressBar(receivedPercent, progressbarWidth, shortedFileName)
87-
}
61+
if silentTransfer {
62+
return utils.WriteFromReader(conn, f, file.Size, config.DefaultBufferSize)
8863
}
89-
if !silentTransfer {
90-
fmt.Printf("\r[%d] %s ✓%s\n", fileID, file.Name, strings.Repeat(" ", progressbarWidth))
64+
65+
shortedFileName := utils.ShortedString(file.Name, 10, 8, 3)
66+
fileSize := utils.ConvertByteSizeToHumanReadable(float64(file.Size))
67+
barTitle := fmt.Sprintf("<%s ^ %s>", fileSize, shortedFileName)
68+
if err = utils.DrawRWProgressbar(conn, f, file.Size, config.DefaultBufferSize, progressbarWidth, barTitle); err != nil {
69+
return err
9170
}
71+
fmt.Printf("\r[%d] %s ✓%s\n", fileID, file.Name, strings.Repeat(" ", progressbarWidth))
72+
9273
return nil
9374
}
9475

cmd/root.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ var rootCmd = &cobra.Command{
1515
Short: "relay is an CLI application wich provide transfer files over network.",
1616
Long: `relay is a CLI application for transferring files over network(local or global).
1717
This application will transfer folders within files as exists in source machine.
18+
credit: Amir Mirzaei
19+
mirzayi994@gmail.com
20+
https://github.com/AmirMirzayi
21+
https://www.linkedin.com/in/amir-mirzaei
1822
`,
1923
}
2024

config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
const (
1313
DefaultPort = 55555
1414
DefaultTimeout = 30 * time.Second
15-
DefaultChunkSize = 1024 * 1024
15+
DefaultBufferSize = 1024 * 1024
1616
DefaultProgressbarWidth = 25
1717
DefaultSilent = false
1818
)

host/host.go

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ package host
55
import (
66
"encoding/binary"
77
"encoding/json"
8-
"errors"
98
"fmt"
10-
"io"
119
"net"
1210
"os"
1311
"path/filepath"
14-
"strings"
1512
"time"
1613

1714
"github.com/AmirMirzayi/relay/config"
@@ -20,8 +17,8 @@ import (
2017

2118
// Serve starts a file transfer server that listens on the specified IP and port.
2219
// It serves files located at the provided paths to connected clients.
23-
func Serve(ip net.IP, port, progressbarWidth int, timeout time.Duration, silentTransfer bool, pathes ...string) error {
24-
files, err := getFilesByPathes(pathes...)
20+
func Serve(ip net.IP, port, progressbarWidth int, timeout time.Duration, silentTransfer bool, paths ...string) error {
21+
files, err := getFilesByPaths(paths...)
2522
if err != nil {
2623
return err
2724
}
@@ -53,12 +50,12 @@ func Serve(ip net.IP, port, progressbarWidth int, timeout time.Duration, silentT
5350
return nil
5451
}
5552

56-
func getFilesByPathes(pathes ...string) (config.Files, error) {
53+
func getFilesByPaths(paths ...string) (config.Files, error) {
5754
// preallocate files to args lengths
5855
// but, what if an arg was directory
59-
files := make(config.Files, 0, len(pathes))
56+
files := make(config.Files, 0, len(paths))
6057

61-
for _, path := range pathes {
58+
for _, path := range paths {
6259
fileInfo, err := os.Stat(path)
6360
if err != nil {
6461
return nil, fmt.Errorf("failed to read information of %s, %v", path, err)
@@ -108,33 +105,17 @@ func sendFile(conn net.Conn, file config.File, fileID, progressbarWidth int, sil
108105
}
109106
defer f.Close()
110107

111-
shortedFileName := utils.ShortedString(file.Name, 10, 7, 4)
112-
113-
var totalByteSent int64
114-
buffer := make([]byte, config.DefaultChunkSize)
115-
for {
116-
n, err := f.Read(buffer)
117-
if err != nil {
118-
if errors.Is(err, io.EOF) {
119-
break
120-
}
121-
return fmt.Errorf("failed to buffering file %s, %v", file.Path, err)
122-
}
123-
124-
byteSent, err := conn.Write(buffer[:n])
125-
if err != nil {
126-
return fmt.Errorf("failed to write over network, %v", err)
127-
}
128-
129-
if !silentTransfer {
130-
totalByteSent += int64(byteSent)
131-
sentPercent := int(totalByteSent * 100 / file.Size)
132-
utils.DrawProgressBar(sentPercent, progressbarWidth, shortedFileName)
133-
}
108+
if silentTransfer {
109+
return utils.WriteFromReader(f, conn, file.Size, config.DefaultBufferSize)
134110
}
135-
if !silentTransfer {
136-
fmt.Printf("\r[%d] %s ✓%s\n", fileID, file.Name, strings.Repeat(" ", progressbarWidth))
111+
112+
shortedFileName := utils.ShortedString(file.Name, 10, 8, 3)
113+
fileSize := utils.ConvertByteSizeToHumanReadable(float64(file.Size))
114+
barTitle := fmt.Sprintf("<%s ^ %s>", fileSize, shortedFileName)
115+
if err = utils.DrawRWProgressbar(f, conn, file.Size, config.DefaultBufferSize, progressbarWidth, barTitle); err != nil {
116+
return err
137117
}
118+
fmt.Printf("\r[%d] %s ✓\033[K\n", fileID, file.Name)
138119
return nil
139120
}
140121

@@ -147,7 +128,7 @@ func readDirectoryFilesRecursively(path string, parents ...string) (config.Files
147128

148129
var files []config.File
149130

150-
// we need to sepereate files and directories iteration over entries because of confusation
131+
// we need to separate files and directories iteration over entries because of confusing
151132
for _, entry := range entries {
152133
if entry.IsDir() {
153134
continue

utils/io.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"io"
6+
)
7+
8+
// DrawRWProgressbar reads data from an io.Reader and writes it to an io.Writer with buffering while displaying a progress bar.
9+
func DrawRWProgressbar(r io.Reader, w io.Writer, size, bufferSize int64, barSize int, barTitle string) error {
10+
lr := io.LimitReader(r, size)
11+
rw := io.TeeReader(lr, w)
12+
13+
buffer := make([]byte, bufferSize)
14+
syncedBytes := int64(0)
15+
for syncedBytes < size {
16+
n, err := rw.Read(buffer)
17+
if err != nil {
18+
return fmt.Errorf("failed to sync buffer between network and disk: %v", err)
19+
}
20+
21+
syncedBytes += int64(n)
22+
donePercent := int(syncedBytes * 100 / size)
23+
drawProgressBar(donePercent, barSize, barTitle)
24+
}
25+
return nil
26+
}
27+
28+
// WriteFromReader reads data from an io.Reader and writes it to an io.Writer with buffering.
29+
func WriteFromReader(r io.Reader, w io.Writer, size, bufferSize int64) error {
30+
lr := io.LimitReader(r, size)
31+
rw := io.TeeReader(lr, w)
32+
33+
buffer := make([]byte, bufferSize)
34+
totalBytesRead := int64(0)
35+
for totalBytesRead < size {
36+
_, err := rw.Read(buffer)
37+
if err != nil && err != io.EOF {
38+
return fmt.Errorf("failed to sync buffer between network and disk: %v", err)
39+
}
40+
}
41+
return nil
42+
}

utils/progressbar.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ import (
55
"strings"
66
)
77

8-
func DrawProgressBar(percent, width int, fileName string) {
8+
// drawProgressBar draw percentage progress bar
9+
func drawProgressBar(percent, width int, barName string) {
10+
progress := strings.Repeat("", 100-percent/(100/width))
11+
progress += strings.Repeat("█", percent/(100/width))
912

10-
// draw transferred data progress bar
11-
progressBar := strings.Repeat("", 100-percent/(100/width))
12-
progressBar += strings.Repeat("█", percent/(100/width))
13-
14-
fmt.Printf("\r%d%% [%-*s] %s", percent, width, progressBar, fileName)
13+
fmt.Printf("\r%d%% |%-*s| %s", percent, width, progress, barName)
1514
}

0 commit comments

Comments
 (0)