diff --git a/s3/s3.go b/s3/s3.go index aba51589eca8677931bd47e2ff4a829abbb1e834..43edf170586ad078af45f5476bb017ddef27e1a6 100644 --- a/s3/s3.go +++ b/s3/s3.go @@ -28,13 +28,22 @@ type S3UploadResponse struct { } type S3UploadSettings struct { - MimeType MIMEType - RetrieveSignedUrl bool - ExpiryDuration *time.Duration // Used to set expiry datetime of download links. NB: does not affect deletion of object from S3 bucket. - AddContentDisposition bool - FileName string + MimeType MIMEType + RetrieveSignedUrl bool + ExpiryDuration *time.Duration // Used to set expiry datetime of download links. NB: does not affect deletion of object from S3 bucket. + AddContentDisposition bool + FileName string + GenerateFileNameFromParts bool // Whether the file extension needs to be specified. If true, supply FilePrefix and FileExt. + FilePrefix string // Required when GenerateFileNameFromParts is true + FileExt string // Required when GenerateFileNameFromParts is true } +// Duration constants +const ( + S3ExpiryDuration1Day time.Duration = 24 * time.Hour + S3ExpiryDuration7Days time.Duration = 7 * 24 * time.Hour +) + type MIMEType string const ( @@ -143,6 +152,90 @@ func (s SessionWithHelpers) UploadWithSettings(data []byte, bucket, fileName str return "", nil } +// UploadWithSettingsRevised can be renamed to UploadWithSettings once original function has been deprecated. +func (s SessionWithHelpers) UploadWithSettingsRevised(data []byte, bucket string, settings S3UploadSettings) (S3UploadResponse, error) { + var fileName, uploadUrl string + + if settings.FileName != "" { + fileName = settings.FileName + } + if settings.GenerateFileNameFromParts { + fileName = fmt.Sprintf("%s_%s.%s", settings.FilePrefix, uuid.New().String(), settings.FileExt) + } + + if settings.MimeType == "" { + settings.MimeType = getTypeForFilename(fileName) + } + + putInput := &s3.PutObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(fileName), + ContentType: aws.String(string(settings.MimeType)), + Body: bytes.NewReader(data), + } + + if settings.ExpiryDuration != nil { + expiry := time.Now().Add(*settings.ExpiryDuration) + putInput.Expires = &expiry + } + + _, err := s.S3Session.PutObject(putInput) + if err != nil { + return S3UploadResponse{}, err + } + + if settings.RetrieveSignedUrl { + var headers map[string]string + + fileNameHeader := fileName + if settings.FileName != "" { + fileNameHeader = settings.FileName + } + + if settings.AddContentDisposition { + headers = map[string]string{ + "content-disposition": "attachment; filename=\"" + fileNameHeader + "\"", + } + } + + uploadUrl, err = s.GetSignedDownloadURL(bucket, fileName, 24*time.Hour, headers) + if err != nil { + return S3UploadResponse{}, err + } + + } + + fileSizeInBytes := binary.Size(data) + + response := S3UploadResponse{ + URL: uploadUrl, + Filename: fileName, + Bucket: bucket, + FileSize: fileSizeInBytes, + } + + return response, nil +} + +func (s SessionWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName string, mimeType MIMEType, shouldDownloadInsteadOfOpen bool) (string, error) { + if mimeType == "" { + mimeType = getTypeForFilename(fileName) + } + + expiry := 24 * time.Hour + signedUrl, err := s.UploadWithSettings(data, bucket, fileName, S3UploadSettings{ + MimeType: mimeType, + RetrieveSignedUrl: true, + ExpiryDuration: &expiry, + AddContentDisposition: shouldDownloadInsteadOfOpen, + }) + if err != nil { + return "", err + } + + return signedUrl, nil +} + // GetSignedDownloadURL gets a signed download URL for the duration. If scv is nil, a new session will be created. func (s SessionWithHelpers) GetSignedDownloadURL(bucket string, fileName string, duration time.Duration, headers ...map[string]string) (string, error) { getInput := &s3.GetObjectInput{