2020-03-07 16:55:13 -08:00
|
|
|
package fs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
2022-01-02 13:17:28 +02:00
|
|
|
"net/http"
|
2020-03-07 16:55:13 -08:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
// Local implements local file storage
|
2020-03-07 16:55:13 -08:00
|
|
|
type Local struct {
|
2022-01-02 13:17:28 +02:00
|
|
|
rootDir string
|
2020-03-07 16:55:13 -08:00
|
|
|
}
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
func NewLocal(rootDir string) (*Local, error) {
|
|
|
|
return &Local{rootDir: rootDir}, nil
|
|
|
|
}
|
2020-03-07 16:55:13 -08:00
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
func (l *Local) Open(name string) (http.File, error) {
|
|
|
|
path := filepath.Join(l.rootDir, name)
|
|
|
|
return os.Open(path)
|
|
|
|
}
|
2020-03-07 16:55:13 -08:00
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
func (l *Local) Delete(_ctx context.Context, name string) error {
|
|
|
|
path := filepath.Join(l.rootDir, name)
|
|
|
|
return os.Remove(path)
|
2020-03-07 16:55:13 -08:00
|
|
|
}
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
func (l *Local) Create(_ctx context.Context, name string, reader io.Reader) (int64, error) {
|
2020-03-07 16:55:13 -08:00
|
|
|
var (
|
2022-01-02 13:17:28 +02:00
|
|
|
logger = log.WithField("name", name)
|
|
|
|
path = filepath.Join(l.rootDir, name)
|
2020-03-07 16:55:13 -08:00
|
|
|
)
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
|
|
|
return 0, errors.Wrapf(err, "failed to mkdir: %s", path)
|
2020-03-07 16:55:13 -08:00
|
|
|
}
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
logger.Infof("creating file: %s", path)
|
|
|
|
written, err := l.copyFile(reader, path)
|
2020-03-07 16:55:13 -08:00
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "failed to copy file")
|
|
|
|
}
|
|
|
|
|
2022-01-02 13:17:28 +02:00
|
|
|
logger.Debugf("written %d bytes", written)
|
2020-03-07 16:55:13 -08:00
|
|
|
return written, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Local) copyFile(source io.Reader, destinationPath string) (int64, error) {
|
|
|
|
dest, err := os.Create(destinationPath)
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "failed to create destination file")
|
|
|
|
}
|
|
|
|
|
|
|
|
defer dest.Close()
|
|
|
|
|
|
|
|
written, err := io.Copy(dest, source)
|
|
|
|
if err != nil {
|
|
|
|
return 0, errors.Wrap(err, "failed to copy data")
|
|
|
|
}
|
|
|
|
|
|
|
|
return written, nil
|
|
|
|
}
|