@@ -7,6 +7,7 @@ package storage
7
7
import (
8
8
"context"
9
9
"io"
10
+ "io/ioutil"
10
11
"net/url"
11
12
"os"
12
13
"path/filepath"
@@ -24,13 +25,15 @@ const LocalStorageType Type = "local"
24
25
25
26
// LocalStorageConfig represents the configuration for a local storage
26
27
type LocalStorageConfig struct {
27
- Path string `ini:"PATH"`
28
+ Path string `ini:"PATH"`
29
+ TemporaryPath string `ini:"TEMPORARY_PATH"`
28
30
}
29
31
30
32
// LocalStorage represents a local files storage
31
33
type LocalStorage struct {
32
- ctx context.Context
33
- dir string
34
+ ctx context.Context
35
+ dir string
36
+ tmpdir string
34
37
}
35
38
36
39
// NewLocalStorage returns a local files
@@ -45,9 +48,14 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
45
48
return nil , err
46
49
}
47
50
51
+ if config .TemporaryPath == "" {
52
+ config .TemporaryPath = config .Path + "/tmp"
53
+ }
54
+
48
55
return & LocalStorage {
49
- ctx : ctx ,
50
- dir : config .Path ,
56
+ ctx : ctx ,
57
+ dir : config .Path ,
58
+ tmpdir : config .TemporaryPath ,
51
59
}, nil
52
60
}
53
61
@@ -63,17 +71,37 @@ func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) {
63
71
return 0 , err
64
72
}
65
73
66
- // always override
67
- if err := util . Remove ( p ); err != nil {
74
+ // Create a temporary file to save to
75
+ if err := os . MkdirAll ( l . tmpdir , os . ModePerm ); err != nil {
68
76
return 0 , err
69
77
}
78
+ tmp , err := ioutil .TempFile (l .tmpdir , "upload-*" )
79
+ if err != nil {
80
+ return 0 , err
81
+ }
82
+ tmpRemoved := false
83
+ defer func () {
84
+ if ! tmpRemoved {
85
+ _ = util .Remove (tmp .Name ())
86
+ }
87
+ }()
70
88
71
- f , err := os . Create ( p )
89
+ n , err := io . Copy ( tmp , r )
72
90
if err != nil {
73
91
return 0 , err
74
92
}
75
- defer f .Close ()
76
- return io .Copy (f , r )
93
+
94
+ if err := tmp .Close (); err != nil {
95
+ return 0 , err
96
+ }
97
+
98
+ if err := os .Rename (tmp .Name (), p ); err != nil {
99
+ return 0 , err
100
+ }
101
+
102
+ tmpRemoved = true
103
+
104
+ return n , nil
77
105
}
78
106
79
107
// Stat returns the info of the file
0 commit comments