-
Notifications
You must be signed in to change notification settings - Fork 61
/
uploader.go
115 lines (88 loc) · 1.98 KB
/
uploader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package tus
import (
"bytes"
)
type Uploader struct {
client *Client
url string
upload *Upload
offset int64
aborted bool
uploadSubs []chan Upload
notifyChan chan bool
}
// Subscribes to progress updates.
func (u *Uploader) NotifyUploadProgress(c chan Upload) {
u.uploadSubs = append(u.uploadSubs, c)
}
// Abort aborts the upload process.
// It doens't abort the current chunck, only the remaining.
func (u *Uploader) Abort() {
u.aborted = true
}
// IsAborted returns true if the upload was aborted.
func (u *Uploader) IsAborted() bool {
return u.aborted
}
// Url returns the upload url.
func (u *Uploader) Url() string {
return u.url
}
// Offset returns the current offset uploaded.
func (u *Uploader) Offset() int64 {
return u.offset
}
// Upload uploads the entire body to the server.
func (u *Uploader) Upload() error {
for u.offset < u.upload.size && !u.aborted {
err := u.UploadChunck()
if err != nil {
return err
}
}
return nil
}
// UploadChunck uploads a single chunck.
func (u *Uploader) UploadChunck() error {
data := make([]byte, u.client.Config.ChunkSize)
_, err := u.upload.stream.Seek(u.offset, 0)
if err != nil {
return err
}
size, err := u.upload.stream.Read(data)
if err != nil {
return err
}
body := bytes.NewBuffer(data[:size])
newOffset, err := u.client.uploadChunck(u.url, body, int64(size), u.offset)
if err != nil {
return err
}
u.offset = newOffset
u.upload.updateProgress(u.offset)
u.notifyChan <- true
return nil
}
// Waits for a signal to broadcast to all subscribers
func (u *Uploader) broadcastProgress() {
for _ = range u.notifyChan {
for _, c := range u.uploadSubs {
c <- *u.upload
}
}
}
// NewUploader creates a new Uploader.
func NewUploader(client *Client, url string, upload *Upload, offset int64) *Uploader {
notifyChan := make(chan bool)
uploader := &Uploader{
client,
url,
upload,
offset,
false,
nil,
notifyChan,
}
go uploader.broadcastProgress()
return uploader
}