2014-10-20 13:38:40 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2014-10-20 14:54:42 +02:00
|
|
|
"fmt"
|
|
|
|
"github.com/goamz/goamz/s3"
|
|
|
|
"io"
|
2014-11-10 17:18:24 +01:00
|
|
|
"mime"
|
2014-10-20 14:54:42 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
2014-10-20 13:38:40 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type Storage interface {
|
2014-10-20 14:54:42 +02:00
|
|
|
Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
|
2014-11-10 17:18:41 +01:00
|
|
|
Head(token string, filename string) (contentType string, contentLength uint64, err error)
|
2014-10-20 14:54:42 +02:00
|
|
|
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type LocalStorage struct {
|
2014-10-20 14:54:42 +02:00
|
|
|
Storage
|
|
|
|
basedir string
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewLocalStorage(basedir string) (*LocalStorage, error) {
|
2014-10-20 14:54:42 +02:00
|
|
|
return &LocalStorage{basedir: basedir}, nil
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
2014-11-10 17:18:41 +01:00
|
|
|
func (s *LocalStorage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
|
|
|
|
path := filepath.Join(s.basedir, token, filename)
|
|
|
|
|
|
|
|
var fi os.FileInfo
|
|
|
|
if fi, err = os.Lstat(path); err != nil {
|
2014-11-11 17:31:52 +01:00
|
|
|
return
|
2014-11-10 17:18:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
contentLength = uint64(fi.Size())
|
|
|
|
|
|
|
|
contentType = mime.TypeByExtension(filepath.Ext(filename))
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
|
|
|
path := filepath.Join(s.basedir, token, filename)
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
// content type , content length
|
|
|
|
if reader, err = os.Open(path); err != nil {
|
|
|
|
return
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
var fi os.FileInfo
|
|
|
|
if fi, err = os.Lstat(path); err != nil {
|
2014-11-11 17:31:52 +01:00
|
|
|
return
|
2014-10-20 14:54:42 +02:00
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
contentLength = uint64(fi.Size())
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-11-10 17:18:24 +01:00
|
|
|
contentType = mime.TypeByExtension(filepath.Ext(filename))
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
return
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
2014-10-20 14:54:42 +02:00
|
|
|
var f io.WriteCloser
|
|
|
|
var err error
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
path := filepath.Join(s.basedir, token)
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
|
|
|
|
return err
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
|
|
|
|
fmt.Printf("%s", err)
|
|
|
|
return err
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
defer f.Close()
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
if _, err = io.Copy(f, reader); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
return nil
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type S3Storage struct {
|
2014-10-20 14:54:42 +02:00
|
|
|
Storage
|
|
|
|
bucket *s3.Bucket
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewS3Storage() (*S3Storage, error) {
|
2014-10-20 14:54:42 +02:00
|
|
|
bucket, err := getBucket()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
return &S3Storage{bucket: bucket}, nil
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
2014-11-10 17:18:41 +01:00
|
|
|
func (s *S3Storage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
|
|
|
|
key := fmt.Sprintf("%s/%s", token, filename)
|
|
|
|
|
|
|
|
// content type , content length
|
|
|
|
response, err := s.bucket.Head(key, map[string][]string{})
|
2014-11-11 17:31:52 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
contentType = response.Header.Get("Content-Type")
|
|
|
|
|
2014-11-10 17:18:41 +01:00
|
|
|
contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
|
2014-11-11 17:31:52 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2014-11-10 17:18:41 +01:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
|
|
|
key := fmt.Sprintf("%s/%s", token, filename)
|
|
|
|
|
|
|
|
// content type , content length
|
|
|
|
response, err := s.bucket.GetResponse(key)
|
2014-11-11 17:31:52 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
contentType = response.Header.Get("Content-Type")
|
2014-10-20 14:54:42 +02:00
|
|
|
contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
|
2014-11-11 17:31:52 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2014-10-20 13:38:40 +02:00
|
|
|
|
2014-10-20 14:54:42 +02:00
|
|
|
reader = response.Body
|
|
|
|
return
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
2014-10-20 14:54:42 +02:00
|
|
|
key := fmt.Sprintf("%s/%s", token, filename)
|
|
|
|
err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
|
|
|
|
return err
|
2014-10-20 13:38:40 +02:00
|
|
|
}
|