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.
 
 
 

144 lines
3.3 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. return
  28. }
  29. contentLength = uint64(fi.Size())
  30. contentType = mime.TypeByExtension(filepath.Ext(filename))
  31. return
  32. }
  33. func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
  34. path := filepath.Join(s.basedir, token, filename)
  35. // content type , content length
  36. if reader, err = os.Open(path); err != nil {
  37. return
  38. }
  39. var fi os.FileInfo
  40. if fi, err = os.Lstat(path); err != nil {
  41. return
  42. }
  43. contentLength = uint64(fi.Size())
  44. contentType = mime.TypeByExtension(filepath.Ext(filename))
  45. return
  46. }
  47. func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
  48. var f io.WriteCloser
  49. var err error
  50. path := filepath.Join(s.basedir, token)
  51. if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
  52. return err
  53. }
  54. if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
  55. fmt.Printf("%s", err)
  56. return err
  57. }
  58. defer f.Close()
  59. if _, err = io.Copy(f, reader); err != nil {
  60. return err
  61. }
  62. return nil
  63. }
  64. type S3Storage struct {
  65. Storage
  66. bucket *s3.Bucket
  67. }
  68. func NewS3Storage() (*S3Storage, error) {
  69. bucket, err := getBucket()
  70. if err != nil {
  71. return nil, err
  72. }
  73. return &S3Storage{bucket: bucket}, nil
  74. }
  75. func (s *S3Storage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
  76. key := fmt.Sprintf("%s/%s", token, filename)
  77. // content type , content length
  78. response, err := s.bucket.Head(key, map[string][]string{})
  79. if err != nil {
  80. return
  81. }
  82. contentType = response.Header.Get("Content-Type")
  83. contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
  84. if err != nil {
  85. return
  86. }
  87. return
  88. }
  89. func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
  90. key := fmt.Sprintf("%s/%s", token, filename)
  91. // content type , content length
  92. response, err := s.bucket.GetResponse(key)
  93. if err != nil {
  94. return
  95. }
  96. contentType = response.Header.Get("Content-Type")
  97. contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
  98. if err != nil {
  99. return
  100. }
  101. reader = response.Body
  102. return
  103. }
  104. func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
  105. key := fmt.Sprintf("%s/%s", token, filename)
  106. err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
  107. return err
  108. }