|
|
@ -7,6 +7,7 @@ package storage |
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"context" |
|
|
|
"context" |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
|
|
|
|
"io/ioutil" |
|
|
|
"net/url" |
|
|
|
"net/url" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"path/filepath" |
|
|
|
"path/filepath" |
|
|
@ -25,12 +26,14 @@ const LocalStorageType Type = "local" |
|
|
|
// LocalStorageConfig represents the configuration for a local storage
|
|
|
|
// LocalStorageConfig represents the configuration for a local storage
|
|
|
|
type LocalStorageConfig struct { |
|
|
|
type LocalStorageConfig struct { |
|
|
|
Path string `ini:"PATH"` |
|
|
|
Path string `ini:"PATH"` |
|
|
|
|
|
|
|
TemporaryPath string `ini:"TEMPORARY_PATH"` |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// LocalStorage represents a local files storage
|
|
|
|
// LocalStorage represents a local files storage
|
|
|
|
type LocalStorage struct { |
|
|
|
type LocalStorage struct { |
|
|
|
ctx context.Context |
|
|
|
ctx context.Context |
|
|
|
dir string |
|
|
|
dir string |
|
|
|
|
|
|
|
tmpdir string |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NewLocalStorage returns a local files
|
|
|
|
// NewLocalStorage returns a local files
|
|
|
@ -46,9 +49,14 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if config.TemporaryPath == "" { |
|
|
|
|
|
|
|
config.TemporaryPath = config.Path + "/tmp" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return &LocalStorage{ |
|
|
|
return &LocalStorage{ |
|
|
|
ctx: ctx, |
|
|
|
ctx: ctx, |
|
|
|
dir: config.Path, |
|
|
|
dir: config.Path, |
|
|
|
|
|
|
|
tmpdir: config.TemporaryPath, |
|
|
|
}, nil |
|
|
|
}, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -64,17 +72,37 @@ func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) { |
|
|
|
return 0, err |
|
|
|
return 0, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// always override
|
|
|
|
// Create a temporary file to save to
|
|
|
|
if err := util.Remove(p); err != nil { |
|
|
|
if err := os.MkdirAll(l.tmpdir, os.ModePerm); err != nil { |
|
|
|
return 0, err |
|
|
|
return 0, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
tmp, err := ioutil.TempFile(l.tmpdir, "upload-*") |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
tmpRemoved := false |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if !tmpRemoved { |
|
|
|
|
|
|
|
_ = util.Remove(tmp.Name()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
f, err := os.Create(p) |
|
|
|
n, err := io.Copy(tmp, r) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return 0, err |
|
|
|
return 0, err |
|
|
|
} |
|
|
|
} |
|
|
|
defer f.Close() |
|
|
|
|
|
|
|
return io.Copy(f, r) |
|
|
|
if err := tmp.Close(); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err := os.Rename(tmp.Name(), p); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tmpRemoved = true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return n, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Stat returns the info of the file
|
|
|
|
// Stat returns the info of the file
|
|
|
|