forked from jpillora/go-dropy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.go
130 lines (106 loc) · 2.2 KB
/
file.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package dropy
import (
"io"
"os"
"strings"
"syscall"
"time"
"github.com/NightMan-1/go-dropbox"
)
// FileInfo wraps Dropbox file MetaData to implement os.FileInfo.
type FileInfo struct {
meta *dropbox.Metadata
}
// Name of the file.
func (f *FileInfo) Name() string {
return f.meta.Name
}
// Size of the file.
func (f *FileInfo) Size() int64 {
return int64(f.meta.Size)
}
// IsDir returns true if the file is a directory.
func (f *FileInfo) IsDir() bool {
return f.meta.Tag == "folder"
}
// Sys is not implemented.
func (f *FileInfo) Sys() interface{} {
return nil
}
// ModTime returns the modification time.
func (f *FileInfo) ModTime() time.Time {
return f.meta.ServerModified
}
// Mode returns the file mode flags.
func (f *FileInfo) Mode() os.FileMode {
var m os.FileMode
if f.IsDir() {
m |= os.ModeDir
}
return m
}
// File implements an io.ReadWriteCloser for Dropbox files.
type File struct {
Name string
closed bool
writing bool
reader io.ReadCloser
pipeR *io.PipeReader
pipeW *io.PipeWriter
c *Client
}
// Read implements io.Reader
func (f *File) Read(b []byte) (int, error) {
if f.reader == nil {
if err := f.download(); err != nil {
return 0, err
}
}
return f.reader.Read(b)
}
// Write implements io.Writer.
func (f *File) Write(b []byte) (int, error) {
if !f.writing {
f.writing = true
go func() {
_, err := f.c.Files.Upload(&dropbox.UploadInput{
Mode: dropbox.WriteModeOverwrite,
Path: f.Name,
Mute: true,
Reader: f.pipeR,
})
f.pipeR.CloseWithError(err)
}()
}
return f.pipeW.Write(b)
}
// Close implements io.Closer.
func (f *File) Close() error {
if f.closed {
return &os.PathError{"close", f.Name, syscall.EINVAL}
}
f.closed = true
if f.writing {
if err := f.pipeW.Close(); err != nil {
return err
}
}
if f.reader != nil {
if err := f.reader.Close(); err != nil {
return err
}
}
return nil
}
// download the file.
func (f *File) download() error {
out, err := f.c.Files.Download(&dropbox.DownloadInput{f.Name})
if err != nil {
if strings.HasPrefix(err.Error(), "path/not_found/") {
return &os.PathError{"open", f.Name, syscall.ENOENT}
}
return err
}
f.reader = out.Body
return nil
}