可靠性: 完善 R2 备份恢复与对象生命周期
This commit is contained in:
@@ -871,7 +871,7 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get S3 client")
|
||||
}
|
||||
if _, err := client.PutObject(ctx.Request().Context(), &s3.PutObjectInput{
|
||||
if err := storage.PutObject(ctx.Request().Context(), client, &s3.PutObjectInput{
|
||||
Bucket: aws.String(conf.Upload.ImageBucket),
|
||||
Key: aws.String(uploadKey),
|
||||
Body: bytes.NewReader(uploadData),
|
||||
@@ -894,6 +894,9 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
|
||||
IsDeletingPrevious: opts.IsDeletingPrevious,
|
||||
})
|
||||
if err != nil {
|
||||
if enqueueErr := db.R2DeleteTasks.Enqueue(ctx.Request().Context(), conf.Upload.ImageBucket, []string{uploadKey}); enqueueErr != nil {
|
||||
return errors.Wrapf(enqueueErr, "compensate upload image after metadata failure: %v", err)
|
||||
}
|
||||
return errors.Wrap(err, "create upload image")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
stdctx "context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -121,6 +122,17 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
return
|
||||
}
|
||||
|
||||
var uploadedProfileImages []string
|
||||
profileSaved := false
|
||||
defer func() {
|
||||
if profileSaved || len(uploadedProfileImages) == 0 {
|
||||
return
|
||||
}
|
||||
if err := db.R2DeleteTasks.EnqueueValues(stdctx.Background(), conf.Upload.ImageBucket, uploadedProfileImages); err != nil {
|
||||
logrus.WithError(err).Error("Failed to enqueue uploaded profile image compensation")
|
||||
}
|
||||
}()
|
||||
|
||||
// 处理头像上传(强制 1:1,见 storage.UploadAvatarToS3)
|
||||
avatarURL := currentUser.Avatar // 默认使用原值
|
||||
avatarFile, avatarFileHeader, err := ctx.Request().FormFile("avatar")
|
||||
@@ -146,6 +158,7 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to upload avatar")
|
||||
} else {
|
||||
avatarURL = uploadedURL
|
||||
uploadedProfileImages = append(uploadedProfileImages, uploadedURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +190,7 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to upload background")
|
||||
} else {
|
||||
backgroundURL = uploadedURL
|
||||
uploadedProfileImages = append(uploadedProfileImages, uploadedURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +214,7 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
logrus.WithContext(ctx.Request().Context()).WithError(err).Error("Failed to upload QRbackgroundImage")
|
||||
} else {
|
||||
backgroundImageURL = uploadedURL
|
||||
uploadedProfileImages = append(uploadedProfileImages, uploadedURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +283,7 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
}
|
||||
ctx.SetInternalErrorFlash()
|
||||
} else if passwordChanged {
|
||||
profileSaved = true
|
||||
// 密码修改成功且其余资料也保存成功:强制登出重登。
|
||||
// 先 Flush 清会话再写入 flash,保证提示能带到登录页显示。
|
||||
ctx.Session.Flush()
|
||||
@@ -275,6 +291,7 @@ func UpdateProfile(ctx context.Context, f form.UpdateProfile) {
|
||||
ctx.Redirect("/login")
|
||||
return
|
||||
} else {
|
||||
profileSaved = true
|
||||
ctx.SetSuccessFlash(i18n.T(ctx.Lang(), "admin.flash.profileUpdated"))
|
||||
}
|
||||
ctx.Redirect("/user/profile")
|
||||
|
||||
Reference in New Issue
Block a user