@@ -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
@@ -46,9 +49,14 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
46
49
return nil , err
47
50
}
48
51
52
+ if config .TemporaryPath == "" {
53
+ config .TemporaryPath = config .Path + "/tmp"
54
+ }
55
+
49
56
return & LocalStorage {
50
- ctx : ctx ,
51
- dir : config .Path ,
57
+ ctx : ctx ,
58
+ dir : config .Path ,
59
+ tmpdir : config .TemporaryPath ,
52
60
}, nil
53
61
}
54
62
@@ -64,17 +72,37 @@ func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) {
64
72
return 0 , err
65
73
}
66
74
67
- // always override
68
- if err := util . Remove ( p ); err != nil {
75
+ // Create a temporary file to save to
76
+ if err := os . MkdirAll ( l . tmpdir , os . ModePerm ); err != nil {
69
77
return 0 , err
70
78
}
79
+ tmp , err := ioutil .TempFile (l .tmpdir , "upload-*" )
80
+ if err != nil {
81
+ return 0 , err
82
+ }
83
+ tmpRemoved := false
84
+ defer func () {
85
+ if ! tmpRemoved {
86
+ _ = util .Remove (tmp .Name ())
87
+ }
88
+ }()
71
89
72
- f , err := os . Create ( p )
90
+ n , err := io . Copy ( tmp , r )
73
91
if err != nil {
74
92
return 0 , err
75
93
}
76
- defer f .Close ()
77
- return io .Copy (f , r )
94
+
95
+ if err := tmp .Close (); err != nil {
96
+ return 0 , err
97
+ }
98
+
99
+ if err := os .Rename (tmp .Name (), p ); err != nil {
100
+ return 0 , err
101
+ }
102
+
103
+ tmpRemoved = true
104
+
105
+ return n , nil
78
106
}
79
107
80
108
// Stat returns the info of the file
0 commit comments