package cicd import ( "bytes" "mime" "os" "path/filepath" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/pkg/errors" ) // DirectoryIterator represents an iterator of a specified directory type DirectoryIterator struct { dir string filePaths []string bucket string keyPrefix string acl string next struct { path string f *os.File } err error } // NewDirectoryIterator builds a new DirectoryIterator func NewDirectoryIterator(bucket, keyPrefix, dir, acl string) s3manager.BatchUploadIterator { var paths []string filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if !info.IsDir() { paths = append(paths, path) } return nil }) return &DirectoryIterator{ dir: dir, filePaths: paths, bucket: bucket, keyPrefix: keyPrefix, acl: acl, } } // Next returns whether next file exists or not func (di *DirectoryIterator) Next() bool { if len(di.filePaths) == 0 { di.next.f = nil return false } f, err := os.Open(di.filePaths[0]) di.err = err di.next.f = f di.next.path = di.filePaths[0] di.filePaths = di.filePaths[1:] return true && di.Err() == nil } // Err returns error of DirectoryIterator func (di *DirectoryIterator) Err() error { return errors.WithStack(di.err) } // UploadObject uploads a file func (di *DirectoryIterator) UploadObject() s3manager.BatchUploadObject { f := di.next.f var acl *string if di.acl != "" { acl = aws.String(di.acl) } buffer, contentType, rerr := readFile(f) nextPath, _ := filepath.Rel(di.dir, di.next.path) return s3manager.BatchUploadObject{ Object: &s3manager.UploadInput{ Bucket: aws.String(di.bucket), Key: aws.String(filepath.Join(di.keyPrefix, nextPath)), Body: bytes.NewReader(buffer), ContentType: aws.String(contentType), ACL: acl, }, After: func() error { if rerr != nil { return rerr } return f.Close() }, } } func readFile(f *os.File) ([]byte, string, error) { // Get file size and read the file content into a buffer fileInfo, err := f.Stat() if err != nil { panic(err) return nil, "", err } var size int64 = fileInfo.Size() buffer := make([]byte, size) f.Read(buffer) ext := filepath.Ext(f.Name()) contentType := mime.TypeByExtension(ext) //f.Seek(0, io.SeekStart) //ctBuf := make([]byte, 512) //f.Read(ctBuf) //contentType = http.DetectContentType(ctBuf) return buffer, contentType, nil }