You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

127 lines
3.1 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/goamz/goamz/s3"
  5. "io"
  6. "mime"
  7. "os"
  8. "path/filepath"
  9. "strconv"
  10. )
  11. type Storage interface {
  12. Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
  13. Head(token string, filename string) (contentType string, contentLength uint64, err error)
  14. Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
  15. }
  16. type LocalStorage struct {
  17. Storage
  18. basedir string
  19. }
  20. func NewLocalStorage(basedir string) (*LocalStorage, error) {
  21. return &LocalStorage{basedir: basedir}, nil
  22. }
  23. func (s *LocalStorage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
  24. path := filepath.Join(s.basedir, token, filename)
  25. var fi os.FileInfo
  26. if fi, err = os.Lstat(path); err != nil {
  27. }
  28. contentLength = uint64(fi.Size())
  29. contentType = mime.TypeByExtension(filepath.Ext(filename))
  30. return
  31. }
  32. func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
  33. path := filepath.Join(s.basedir, token, filename)
  34. // content type , content length
  35. if reader, err = os.Open(path); err != nil {
  36. return
  37. }
  38. var fi os.FileInfo
  39. if fi, err = os.Lstat(path); err != nil {
  40. }
  41. contentLength = uint64(fi.Size())
  42. contentType = mime.TypeByExtension(filepath.Ext(filename))
  43. return
  44. }
  45. func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
  46. var f io.WriteCloser
  47. var err error
  48. path := filepath.Join(s.basedir, token)
  49. if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
  50. return err
  51. }
  52. if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
  53. fmt.Printf("%s", err)
  54. return err
  55. }
  56. defer f.Close()
  57. if _, err = io.Copy(f, reader); err != nil {
  58. return err
  59. }
  60. return nil
  61. }
  62. type S3Storage struct {
  63. Storage
  64. bucket *s3.Bucket
  65. }
  66. func NewS3Storage() (*S3Storage, error) {
  67. bucket, err := getBucket()
  68. if err != nil {
  69. return nil, err
  70. }
  71. return &S3Storage{bucket: bucket}, nil
  72. }
  73. func (s *S3Storage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
  74. key := fmt.Sprintf("%s/%s", token, filename)
  75. // content type , content length
  76. response, err := s.bucket.Head(key, map[string][]string{})
  77. contentType = ""
  78. contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
  79. return
  80. }
  81. func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
  82. key := fmt.Sprintf("%s/%s", token, filename)
  83. // content type , content length
  84. response, err := s.bucket.GetResponse(key)
  85. contentType = ""
  86. contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
  87. reader = response.Body
  88. return
  89. }
  90. func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
  91. key := fmt.Sprintf("%s/%s", token, filename)
  92. err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
  93. return err
  94. }