// Download using to download file from S3 by bucket and key func Download(session *session.Session, bucket, key, path string) { file, err := os.Create(path) logger.Process(err, "Can't create file") defer file.Close() client := s3manager.NewDownloader(session) _, err = client.Download(file, &s3.GetObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), }) logger.Process(err, "Can't retrieve object from S3") }
// DownloadFile using result of GetPresignedURL for downloading file by pre-signed URL func DownloadFile(url, path string) { resp, err := http.DefaultClient.Get(url) logger.Process(err, "Failed to download a file by pre-signed URL") defer func() { // Drain and close the body to let the Transport reuse the connection io.Copy(ioutil.Discard, resp.Body) resp.Body.Close() }() body, err := ioutil.ReadAll(resp.Body) logger.Process(err, "Failed to get a body from HTTP request") err = ioutil.WriteFile(path, body, 0777) logger.Process(err, "Failed to create a file from a body of HTTP request") }
func main() { log.SetFlags(log.Lshortfile | log.LstdFlags) comm, err := getCommand() logger.Process(err, "") fmt.Println("Command:", comm) err = flag.CommandLine.Parse(os.Args[2:]) logger.Process(err, "Can't parse arguments") if *bucket == "" || *key == "" { fmt.Println("Please, specify valid parameters for command!") os.Exit(1) } session := session.New(awsconfig.New()) switch comm { case "presigned": link, err := command.GetPresignedURL(session, *bucket, *key) logger.Process(err, "Can't generate pre-signed S3 URL") log.Println("Pre-signed URL:", link) case "download": log.Println("Start downloading file...") dest := *key if *pathToFile != "" { dest = *pathToFile + "/" + *key } if *url != "" { command.DownloadFile(*url, dest) } else { command.Download(session, *bucket, *key, dest) } fmt.Println("File is downloaded!") case "upload": if *pathToFile == "" { fmt.Println("Can't proceed without path to file") os.Exit(1) } file, err := os.Open(*pathToFile) logger.Process(err, "Failed to open a file") defer file.Close() info, err := file.Stat() logger.Process(err, "Failed to get info about file") switch mode := info.Mode(); { case mode.IsDir(): command.UploadDirectory(session, *bucket, *key, *pathToFile, *keepRootFolder) case mode.IsRegular(): command.UploadFile(session, *bucket, *key, file) } } }
// GetPresignedURL generate pre-signed URL, which can be used for download file func GetPresignedURL(session *session.Session, bucket, key string) (string, error) { client := s3.New(session) request, _ := client.GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), }) url, err := request.Presign(10 * time.Minute) logger.Process(err, "Failed to create pre-signed URL") return url, err }
// UploadFile will upload file to specific S3 bucket func UploadFile(session *session.Session, bucket, key string, file *os.File) { service := s3manager.NewUploader(session) resp, err := service.Upload(&s3manager.UploadInput{ Bucket: aws.String(bucket), Key: aws.String(key), Body: file, ContentType: aws.String(getContentType(file)), }) logger.Process(err, "Can't upload file") fmt.Println("File was successfully uploaded! Location:", resp.Location) }
// UploadDirectory will upload directory and all it's content while keeping it structure func UploadDirectory(session *session.Session, bucket, key, dir string, keep bool) { var wg sync.WaitGroup err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if !info.IsDir() { file, err := os.Open(path) if err == nil { t := getPathInsideFolder(path, getFolderName(dir), keep) go func() { wg.Add(1) UploadFile(session, bucket, key+t, file) file.Close() wg.Done() }() } } return nil }) wg.Wait() logger.Process(err, "Can't process directory") fmt.Println("Directory was successfully uploaded!") }