当前位置: 首页 > 工具软件 > S3Uploader > 使用案例 >

aws-s3服务GO版本上传&删除

龚铭
2023-12-01

上代码:

#路由
route.POST("/editSpace", controller.EditspaceHandler)

func EditspaceHandler(c *gin.Context) {

	portrait, err := c.FormFile("portrait") // 获取文件
	if err != nil {
		ResponseErrorWithMsg(c, CodeInvalidParam, err)
		return
	}
	cover, err := c.FormFile("cover") // 获取文件
	if err != nil {
		ResponseErrorWithMsg(c, CodeInvalidParam, err)
		return
	}
	username, isBool := c.GetPostForm("username")
	//没有这个字段
	if !isBool {
		ResponseError(c, CodeInvalidParam)
		return
	}
	if username == "" {
		ResponseErrorWithMsg(c, CodeInvalidParam, "username is required ")
		return
	}
	bio, isBool := c.GetPostForm("bio")
	//没有这个字段
	if !isBool {
		ResponseError(c, CodeInvalidParam)
		return
	}
	//自愿选择空内容 也是可以
	//if bio == "" {
	//
	//}

	userid, isBool := c.GetPostForm("userid")
	if !isBool {
		ResponseError(c, CodeInvalidParam)
		return
	}
	if userid == "" {
		ResponseErrorWithMsg(c, CodeInvalidParam, "userid is required ")
		return
	}
	err = service.NewSpaceService(c.Request.Context()).EditSpaceProfile(portrait, cover, username, bio, userid)
	if err != nil {
		ResponseErrorWithMsg(c, InternalError, err)
		return
	}
	ResponseSuccess(c)
}
func (s *SpaceService) EditSpaceProfile(portrait, cover *multipart.FileHeader, username, bio, userid string) error {
	uid, _ := strconv.Atoi(userid)
	//上传新头像
	url, err := AWSUploadWithClient(portrait, svc, "userportrait")
	if err != nil {
		return err
	}
	usvc := NewUserService(context.Background())
	userinfo, err := usvc.repo.GetUserInfoByUserid(userid)
	if err != nil {
		return err
	}
	if userinfo.Avatar != DefaultUserAvatar {
		split := strings.Split(userinfo.Avatar, "/")
		key := split[len(split)-2] + "/" + split[len(split)-1]
		//删除旧头像
		err = AWSDeleteWithClient(svc, key)
		if err != nil {
			return err
		}
	}
	coverurl, err := AWSUploadWithClient(cover, svc, "usercover")
	if err != nil {
		return err
	}
	if userinfo.Cover != DefaultUserCover {
		split := strings.Split(userinfo.Cover, "/")
		key := split[len(split)-2] + "/" + split[len(split)-1]
		//删除旧封面
		err = AWSDeleteWithClient(svc, key)
		if err != nil {
			return err
		}
	}
	var user models.User
	user.Avatar = url
	user.Userid = uid
	user.Cover = coverurl
	user.Name = username
	user.Introduction = bio
	return usvc.repo.UpdateUserByUserid(user)

}

上传图片的也可以参考我上一篇aws的文章

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
	"go.uber.org/zap"
	"mime/multipart"
	"os"
	"stargate_backend/utils"
	"strconv"
)
var (
	// IAM账户  需要在IAM添加合适的访问策略 才有s3服务的访问权限
	accessKey = "AKIArrrrrrMUrrrrrrrHB"                     //""
	secretKey = "bsrrrrryt4vrrrrr8Gmt2rNrrrrrrrrrkvHcgy6l" //""
	//根用户 MFA 非最佳实践 但具有根权限 无需配置权限 可以直接使用
	//accessKey = "AKIASrrrrrrrrrrrNBX5C"                     //""
	//secretKey = "Zfrrrrrr/UXrrrrrrrrrrrrrrrN9wnirrrrrGbpS" //""
	region = "ap-northeast-1"

	endpoint = "https://s3.ap-northeast-1.amazonaws.com/"
	//endpoint = "arn:aws:s3:ap-northeast-1:144458791721:accesspoint/gate3-static"
	svc *s3.S3
	//AWSBatchDeleteClient *s3manager.BatchDelete
)
func AWSInit() error {
	//只要不修改session,session就可以安全的并发使用。
	sess, err := session.NewSession(&aws.Config{
		Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
		Endpoint:    aws.String(endpoint),
		Region:      aws.String(region),
		//minio:true,oss:false
		S3ForcePathStyle: aws.Bool(false),
		//SDK 支持使用客户端 TLS 证书配置的环境和会话选项,这些证书作为客户端 TLS 握手的一部分发送以进行客户端身份验证。
		//如果使用,则需要 Cert 和 Key 值。如果缺少一个,或者无法加载文件的内容,则会返回一个错误。
		//ClientTLSCert:              nil,
		//ClientTLSKey:               nil,
	})
	if err != nil {
		panic(err)

	}

	svc = s3.New(sess)
	//AWSBatchDeleteClient = s3manager.NewBatchDelete(sess)

	return err
}
func AWSDeleteWithClient(svc *s3.S3, key string) error {
	input := &s3.DeleteObjectInput{
		Bucket:                    aws.String("bucket-name"),
		BypassGovernanceRetention: nil,
		ExpectedBucketOwner:       nil,
		Key:                       aws.String(key),
		MFA:                       nil,
		RequestPayer:              nil,
		VersionId:                 nil,
	}
	object, err := svc.DeleteObject(input)
	if err != nil {
		zap.L().Error("delete from aws failed...", zap.Error(err))
		return err
	}
	fmt.Printf("delete object output:%#v\n", object)
	return err
}

//S3 上传管理器确定文件是否可以拆分为更小的部分并并行上传。您可以自定义并行上传的数量和上传部分的大小。
func AWSUploadWithClient(file *multipart.FileHeader, svc *s3.S3, dir string) (string, error) {
	uploader := s3manager.NewUploaderWithClient(svc, func(u *s3manager.Uploader) {
		//定义将在内存中缓冲25个MiB的策略
		//u.BufferProvider = s3manager.NewBufferedReadSeekerWriteToPool(25 * 1024 * 1024)
		//指定要上传的每个部分的缓冲区大小(以字节为单位)。每个部分的最小大小为 5 MB。 DefaultUploadPartSize
		u.PartSize = 64 * 1024 * 1024 // 每个部分 64MB
		//	指定要并行上传的part数量。 默认为5
		u.Concurrency = s3manager.DefaultUploadConcurrency
	})
	open, err := file.Open() //  可以通过一个*multipart.FileHeader 的open() 方法的获取一个multipart.File文件 它实现了io.Reader接口
	if err != nil {
		return "", err
	}
	id, _ := utils.GenID()
	uploadOutput, err := uploader.Upload(&s3manager.UploadInput{
		Body:   open,                                     // io.Reader类型
		Bucket: aws.String("bucketname"),                      // 指定要上传的bucket
		Key:    aws.String(dir + "/" + strconv.Itoa(id)), // 如果bucket下边有文件夹,那么通过在key前加上指定路径,来达到上传到指定文件夹的效果。
		ACL:    aws.String("public-read"),                // 指定ACL权限。一般上传图片类的都是期望可以在前端通过url获取资源的,为public-read。具体可以参考 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/acl-overview.html#CannedACL
	})
	if err != nil {
		if multierr, ok := err.(s3manager.MultiUploadFailure); ok {
			// Process error and its associated uploadID
			fmt.Println("Error:", multierr.Code(), multierr.Message(), multierr.UploadID())
		} else {
			// Process error generically
			fmt.Println("Error:", err.Error())
		}

		return "", err
	}
	//eg:https://bucketname.s3.ap-northeast-1.amazonaws.com/users/7158634979000321
	url := "https://bucketname.s3.ap-northeast-1.amazonaws.com/" + dir + "/" + strconv.Itoa(id)
	fmt.Printf("UploadID:%s\n", uploadOutput.UploadID)
	fmt.Printf("ETag:%s\n", *uploadOutput.ETag)
	fmt.Printf("Location:%s\n", uploadOutput.Location)
	return url, err
}

 类似资料: