mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-12-01 16:40:19 +01:00
28fc9c73f5
* Support Range header for GET * Adds 'Accept-Ranges: bytes' header to handlers * proper param name in error * bump gdrive dependecies * refactor CloseCheck to avoid panic on nil, remove range/audio/video special handling on get handler * refactor CloseCheck to avoid panic on nil, handle range with no limit * refactor CloseCheck to avoid panic on nil, handle range in gdrive storage * refactor CloseCheck to avoid panic on nil * handle range with no limit * lint * bump deps * go mod tidy * gofmt * cr fixes, replace deprecated ioutil.NopCloser * linting * do not write to file by default * fix storj --------- Co-authored-by: Vladislav Grubov <vladgrubov@gmail.com>
138 lines
2.9 KiB
Go
138 lines
2.9 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
// LocalStorage is a local storage
|
|
type LocalStorage struct {
|
|
Storage
|
|
basedir string
|
|
logger *log.Logger
|
|
}
|
|
|
|
// NewLocalStorage is the factory for LocalStorage
|
|
func NewLocalStorage(basedir string, logger *log.Logger) (*LocalStorage, error) {
|
|
return &LocalStorage{basedir: basedir, logger: logger}, nil
|
|
}
|
|
|
|
// Type returns the storage type
|
|
func (s *LocalStorage) Type() string {
|
|
return "local"
|
|
}
|
|
|
|
// Head retrieves content length of a file from storage
|
|
func (s *LocalStorage) Head(_ context.Context, token string, filename string) (contentLength uint64, err error) {
|
|
path := filepath.Join(s.basedir, token, filename)
|
|
|
|
var fi os.FileInfo
|
|
if fi, err = os.Lstat(path); err != nil {
|
|
return
|
|
}
|
|
|
|
contentLength = uint64(fi.Size())
|
|
|
|
return
|
|
}
|
|
|
|
// Get retrieves a file from storage
|
|
func (s *LocalStorage) Get(_ context.Context, token string, filename string, rng *Range) (reader io.ReadCloser, contentLength uint64, err error) {
|
|
path := filepath.Join(s.basedir, token, filename)
|
|
|
|
var file *os.File
|
|
|
|
// content type , content length
|
|
if file, err = os.Open(path); err != nil {
|
|
return
|
|
}
|
|
reader = file
|
|
|
|
var fi os.FileInfo
|
|
if fi, err = os.Lstat(path); err != nil {
|
|
return
|
|
}
|
|
|
|
contentLength = uint64(fi.Size())
|
|
if rng != nil {
|
|
contentLength = rng.AcceptLength(contentLength)
|
|
if _, err = file.Seek(int64(rng.Start), 0); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Delete removes a file from storage
|
|
func (s *LocalStorage) Delete(_ context.Context, token string, filename string) (err error) {
|
|
metadata := filepath.Join(s.basedir, token, fmt.Sprintf("%s.metadata", filename))
|
|
_ = os.Remove(metadata)
|
|
|
|
path := filepath.Join(s.basedir, token, filename)
|
|
err = os.Remove(path)
|
|
return
|
|
}
|
|
|
|
// Purge cleans up the storage
|
|
func (s *LocalStorage) Purge(_ context.Context, days time.Duration) (err error) {
|
|
err = filepath.Walk(s.basedir,
|
|
func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
if info.ModTime().Before(time.Now().Add(-1 * days)) {
|
|
err = os.Remove(path)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
// IsNotExist indicates if a file doesn't exist on storage
|
|
func (s *LocalStorage) IsNotExist(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
|
|
return os.IsNotExist(err)
|
|
}
|
|
|
|
// Put saves a file on storage
|
|
func (s *LocalStorage) Put(_ context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
|
var f io.WriteCloser
|
|
var err error
|
|
|
|
path := filepath.Join(s.basedir, token)
|
|
|
|
if err = os.MkdirAll(path, 0700); err != nil && !os.IsExist(err) {
|
|
return err
|
|
}
|
|
|
|
f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
|
defer CloseCheck(f)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err = io.Copy(f, reader); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *LocalStorage) IsRangeSupported() bool { return true }
|