sync.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // +build example
  2. package main
  3. import (
  4. "flag"
  5. "fmt"
  6. "mime"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "github.com/aws/aws-sdk-go/aws"
  11. "github.com/aws/aws-sdk-go/aws/session"
  12. "github.com/aws/aws-sdk-go/service/s3/s3manager"
  13. )
  14. // SyncFolderIterator is used to upload a given folder
  15. // to Amazon S3.
  16. type SyncFolderIterator struct {
  17. bucket string
  18. fileInfos []fileInfo
  19. err error
  20. }
  21. type fileInfo struct {
  22. key string
  23. fullpath string
  24. }
  25. // NewSyncFolderIterator will walk the path, and store the key and full path
  26. // of the object to be uploaded. This will return a new SyncFolderIterator
  27. // with the data provided from walking the path.
  28. func NewSyncFolderIterator(path, bucket string) *SyncFolderIterator {
  29. metadata := []fileInfo{}
  30. filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
  31. if !info.IsDir() {
  32. key := strings.TrimPrefix(p, path)
  33. metadata = append(metadata, fileInfo{key, p})
  34. }
  35. return nil
  36. })
  37. return &SyncFolderIterator{
  38. bucket,
  39. metadata,
  40. nil,
  41. }
  42. }
  43. // Next will determine whether or not there is any remaining files to
  44. // be uploaded.
  45. func (iter *SyncFolderIterator) Next() bool {
  46. return len(iter.fileInfos) > 0
  47. }
  48. // Err returns any error when os.Open is called.
  49. func (iter *SyncFolderIterator) Err() error {
  50. return iter.err
  51. }
  52. // UploadObject will prep the new upload object by open that file and constructing a new
  53. // s3manager.UploadInput.
  54. func (iter *SyncFolderIterator) UploadObject() s3manager.BatchUploadObject {
  55. fi := iter.fileInfos[0]
  56. iter.fileInfos = iter.fileInfos[1:]
  57. body, err := os.Open(fi.fullpath)
  58. if err != nil {
  59. iter.err = err
  60. }
  61. extension := filepath.Ext(fi.key)
  62. mimeType := mime.TypeByExtension(extension)
  63. if mimeType == "" {
  64. mimeType = "binary/octet-stream"
  65. }
  66. input := s3manager.UploadInput{
  67. Bucket: &iter.bucket,
  68. Key: &fi.key,
  69. Body: body,
  70. ContentType: &mimeType,
  71. }
  72. return s3manager.BatchUploadObject{
  73. &input,
  74. nil,
  75. }
  76. }
  77. // Upload a directory to a given bucket
  78. //
  79. // Usage:
  80. // sync <params>
  81. // -region <region> // required
  82. // -bucket <bucket> // required
  83. // -path <path> // required
  84. func main() {
  85. bucketPtr := flag.String("bucket", "", "bucket to upload to")
  86. regionPtr := flag.String("region", "", "region to be used when making requests")
  87. pathPtr := flag.String("path", "", "path of directory to be synced")
  88. flag.Parse()
  89. sess := session.New(&aws.Config{
  90. Region: regionPtr,
  91. })
  92. uploader := s3manager.NewUploader(sess)
  93. iter := NewSyncFolderIterator(*pathPtr, *bucketPtr)
  94. if err := uploader.UploadWithIterator(aws.BackgroundContext(), iter); err != nil {
  95. fmt.Fprintf(os.Stderr, "unexpected error has occurred: %v", err)
  96. }
  97. if err := iter.Err(); err != nil {
  98. fmt.Fprintf(os.Stderr, "unexpected error occurred during file walking: %v", err)
  99. }
  100. fmt.Println("Success")
  101. }