Reputation: 1081
I have some images that I am uploading to my s3 account using the official amazon s3 package . My images are typically around 250 - 350 KB so small images, however they take around 8 or 9 seconds to upload which seems excessive any suggestions on improving speed would be great. This is my code and if I take the resizing image code off it still takes a good 8 or 9 seconds still .
func UploadStreamImage(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
var buff bytes.Buffer
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
var buf bytes.Buffer
sess, _ := session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
Credentials: credentials.NewStaticCredentials(aws_access_key_id, aws_secret_access_key, ""),
})
svc := s3.New(sess)
file, handler, err := r.FormFile("file")
if err != nil {
log_errors(" error on upload",err.Error(),w)
fmt.Println("Error Uploading Image")
return
}
defer file.Close()
img,err := imaging.Decode(file)
if err != nil {
print("Imaging Open error")
log_errors("Error decoding",err.Error(),w)
return
}
imgSize,err := strconv.Atoi(r.FormValue("imgsize"))
if err != nil {
println("Error converting to integer")
log_errors("Error converting to integer",err.Error(),w)
return
}
b := img.Bounds()
heightImg := b.Max.Y
widthImg := b.Max.X
// resize image
height := int(float64(heightImg) * .23)
width := int(float64(widthImg) * .23)
if imgSize < 401 {
height = int(float64(heightImg) * 1)
width = int(float64(widthImg) * 1)
} else if imgSize >= 401 && imgSize < 900 {
height = int(float64(heightImg) * .68)
width = int(float64(widthImg) * .68)
println("Middle Image")
} else if imgSize >= 900 && imgSize < 1300 {
height = int(float64(heightImg) * .45)
width = int(float64(widthImg) * .45)
} else if imgSize >= 1301 && imgSize < 1700 {
height = int(float64(heightImg) * .40)
width = int(float64(widthImg) * .40)
}
new_img := imaging.Resize(img,width,height, imaging.Lanczos)
// end resize
err = imaging.Encode(&buf,new_img, imaging.JPEG)
if err != nil {
log.Println(err)
log_errors(" error encoding file",err.Error(),w)
return
}
r := bytes.NewReader(buf.Bytes())
read_file,err := ioutil.ReadAll(r)
if err != nil {
fmt.Println("Error Reading file")
log_errors(" error reading file",err.Error(),w)
return
}
file.Read(read_file)
fileBytes := bytes.NewReader(read_file)
fileSize, err := buff.ReadFrom(fileBytes)
if err != nil {
log_errors(" error fileSize",err.Error(),w)
return
}
fileType := http.DetectContentType(read_file)
path := handler.Filename
params := &s3.PutObjectInput{
Bucket: aws.String("bucket name"),
Key: aws.String(path),
Body: fileBytes,
ContentLength: aws.Int64(fileSize),
ContentType: aws.String(fileType),
}
resp, err := svc.PutObject(params)
if err != nil {
fmt.Printf("bad response: %s", err)
log_errors("error in putObject",err.Error(),w)
return
}
fmt.Println(w,"Done")
}()
wg.Wait()
}
Upvotes: 2
Views: 2700
Reputation: 4791
Improving speed?
this is subjective one; depends on many factors such as server uplink, client uplink, etc.
Instead, I will provide my inputs to improve your code snippets:
sync.WaitGroup
- I do not see a benefit as per your code flow, you just create and wait for goroutine to complete. Instead use without WaitGroup. Tip:
Do not use feature for sake/buzz; use it when needed.bytes.Buffer
and Reader
, when you can accomplish without it. For e.g. getting fileSize after the resize, just do buf.Len()
.func
and call it as goroutine.I have updated your code snippet (I have not tested your code, so please fix/improve it as required):
func UploadStreamImage(w http.ResponseWriter, r *http.Request) {
file, handler, err := r.FormFile("file")
if err != nil {
log_errors(" error on upload", err.Error(), w)
fmt.Println("Error Uploading Image")
return
}
defer file.Close()
// Suggestion: You can calculate the file size from bytes.
// instead getting it from form; since after resize image will change
imgSize, err := strconv.Atoi(r.FormValue("imgsize"))
if err != nil {
println("Error converting to integer")
log_errors("Error converting to integer", err.Error(), w)
return
}
img, err := imaging.Decode(file)
if err != nil {
print("Imaging Open error")
log_errors("Error decoding", err.Error(), w)
return
}
b := img.Bounds()
heightImg := b.Max.Y
widthImg := b.Max.X
// resize image
height := int(float64(heightImg) * .23)
width := int(float64(widthImg) * .23)
if imgSize < 401 {
height = int(float64(heightImg) * 1)
width = int(float64(widthImg) * 1)
} else if imgSize >= 401 && imgSize < 900 {
height = int(float64(heightImg) * .68)
width = int(float64(widthImg) * .68)
println("Middle Image")
} else if imgSize >= 900 && imgSize < 1300 {
height = int(float64(heightImg) * .45)
width = int(float64(widthImg) * .45)
} else if imgSize >= 1301 && imgSize < 1700 {
height = int(float64(heightImg) * .40)
width = int(float64(widthImg) * .40)
}
new_img := imaging.Resize(img, width, height, imaging.Lanczos)
// end resize
var buf bytes.Buffer
err = imaging.Encode(&buf, new_img, imaging.JPEG)
if err != nil {
log.Println(err)
log_errors(" error encoding file", err.Error(), w)
return
}
fileType := http.DetectContentType(buf.Bytes())
fileSize := buf.Len()
path := handler.Filename
params := &s3.PutObjectInput{
Bucket: aws.String("bucket name"),
Key: aws.String(path),
Body: bytes.NewReader(buf.Bytes()),
ContentLength: aws.Int64(fileSize),
ContentType: aws.String(fileType),
}
resp, err := svc.PutObject(params)
if err != nil {
fmt.Printf("bad response: %s", err)
log_errors("error in putObject", err.Error(), w)
return
}
fmt.Println("Done", resp)
}
Upvotes: 4