Golang amazon s3如何更快地上传图片

时间:2017-07-07 23:14:07

标签: go amazon-s3

我有一些图像,我使用官方的亚马逊s3包上传到我的s3帐户。我的图像通常大约250 - 350 KB这么小的图像,但它们需要大约8或9秒上传,这似乎过多任何提高速度的建议都会很棒。这是我的代码,如果我将调整大小的图像代码关闭,它仍然需要8或9秒钟。

      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()

}

1 个答案:

答案 0 :(得分:2)

Improving speed?这是主观的;取决于许多因素,如服务器上行链路,客户端上行链路等。

相反,我会提供改进您的代码段的输入:

  • 让我们从sync.WaitGroup开始 - 根据您的代码流程,我没有看到任何好处,您只需创建并等待goroutine完成。而不使用WaitGroup。 Tip:不要将功能用于清酒/嗡嗡声;在需要时使用它。
  • 如果没有它,请不要创建多个bytes.BufferReader。对于例如调整大小后获取fileSize,只需执行buf.Len()
  • 如果您要卸载AWS上传,请将上传代码部分提取到单独的func中,并将其称为goroutine。

我已更新您的代码段(我尚未测试您的代码,因此请根据需要修复/改进):

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)
}