I'm trying to upload a directory into Amazon S3 bucket. However, the only way to upload a directory is to iterate through all the files inside the directory and upload them one by one.
I'm using Go to iterate over the files in directory. However, for each file I iterate through, I want to spin off a goroutine that uploads the file while the main thread iterates through the next element in the directory and spins off another goroutine to upload the same.
Any idea on how I can upload all the files in the directory parallelly using Goroutines and Channels?
Revised code snippet that implements a goroutine and a channel to upload files in parallel. But I'm not sure if this is the right implementation.
func uploadDirToS3(dir string, svc *s3.S3) {
fileList := []string{}
filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
fmt.Println("PATH ==> " + path)
fileList = append(fileList, path)
return nil
})
for _, pathOfFile := range fileList[1:] {
channel := make(chan bool)
go uploadFiletoS3(pathOfFile, svc, channel)
<-channel
}
}
func uploadFiletoS3(path string, svc *s3.S3, channel chan bool) {
file, err := os.Open(path)
if err != nil {
fmt.Println(err)
}
defer file.Close()
fileInfo, _ := file.Stat()
size := fileInfo.Size()
buffer := make([]byte, size)
file.Read(buffer)
fileBytes := bytes.NewReader(buffer)
fileType := http.DetectContentType(buffer)
s3Path := file.Name()
params := &s3.PutObjectInput{
Bucket: aws.String("name-of-bucket"),
Key: aws.String(s3Path),
Body: fileBytes,
ContentLength: aws.Int64(size),
ContentType: aws.String(fileType),
}
resp, err := svc.PutObject(params)
if err != nil {
fmt.Println(err)
}
fmt.Printf("response %s", awsutil.StringValue(resp))
close(channel)
}
Any ideas on how I could implement this better? I've looked into WaitGroups but for some reason, I found Channels much easier to understand and implement in this situation.