96 lines
1.9 KiB
Go
96 lines
1.9 KiB
Go
|
package filestore
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
|
||
|
"github.com/tus/tusd"
|
||
|
"github.com/tus/tusd/uid"
|
||
|
)
|
||
|
|
||
|
var defaultFilePerm = os.FileMode(0666)
|
||
|
|
||
|
type FileStore struct {
|
||
|
Path string
|
||
|
}
|
||
|
|
||
|
func (store FileStore) NewUpload(size int64, metaData tusd.MetaData) (id string, err error) {
|
||
|
id = uid.Uid()
|
||
|
info := tusd.FileInfo{
|
||
|
Id: id,
|
||
|
Size: size,
|
||
|
Offset: 0,
|
||
|
MetaData: metaData,
|
||
|
}
|
||
|
|
||
|
// Create .bin file with no content
|
||
|
file, err := os.OpenFile(store.binPath(id), os.O_CREATE|os.O_WRONLY, defaultFilePerm)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
// writeInfo creates the file by itself if necessary
|
||
|
err = store.writeInfo(id, info)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (store FileStore) WriteChunk(id string, offset int64, src io.Reader) error {
|
||
|
file, err := os.OpenFile(store.binPath(id), os.O_WRONLY|os.O_APPEND, defaultFilePerm)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
n, err := io.Copy(file, src)
|
||
|
if n > 0 {
|
||
|
if err := store.setOffset(id, offset+n); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (store FileStore) GetInfo(id string) (tusd.FileInfo, error) {
|
||
|
info := tusd.FileInfo{}
|
||
|
data, err := ioutil.ReadFile(store.infoPath(id))
|
||
|
if err != nil {
|
||
|
return info, err
|
||
|
}
|
||
|
err = json.Unmarshal(data, &info)
|
||
|
return info, err
|
||
|
}
|
||
|
|
||
|
func (store FileStore) binPath(id string) string {
|
||
|
return store.Path + "/" + id + ".bin"
|
||
|
}
|
||
|
|
||
|
func (store FileStore) infoPath(id string) string {
|
||
|
return store.Path + "/" + id + ".info"
|
||
|
}
|
||
|
|
||
|
func (store FileStore) writeInfo(id string, info tusd.FileInfo) error {
|
||
|
data, err := json.Marshal(info)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return ioutil.WriteFile(store.infoPath(id), data, defaultFilePerm)
|
||
|
}
|
||
|
|
||
|
func (store FileStore) setOffset(id string, offset int64) error {
|
||
|
info, err := store.GetInfo(id)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// never decrement the offset
|
||
|
if info.Offset >= offset {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
info.Offset = offset
|
||
|
return store.writeInfo(id, info)
|
||
|
}
|