mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Uploading file to storage asynchronously.
This commit is contained in:
@@ -3,6 +3,7 @@ package dao
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
"nysoure/server/model"
|
"nysoure/server/model"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -35,15 +36,22 @@ func GetUploadingFile(id uint) (*model.UploadingFile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUploadingBlock(id uint, blockIndex int) error {
|
func UpdateUploadingBlock(id uint, blockIndex int) error {
|
||||||
uf := &model.UploadingFile{}
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := db.Where("id = ?", id).First(uf).Error; err != nil {
|
// 使用 FOR UPDATE 锁获取记录
|
||||||
return err
|
uf := &model.UploadingFile{}
|
||||||
}
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", id).First(uf).Error; err != nil {
|
||||||
if blockIndex < 0 || blockIndex >= uf.BlocksCount() {
|
return err
|
||||||
return nil
|
}
|
||||||
}
|
|
||||||
uf.Blocks[blockIndex] = true
|
if blockIndex < 0 || blockIndex >= uf.BlocksCount() {
|
||||||
return db.Save(uf).Error
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
uf.Blocks[blockIndex] = true
|
||||||
|
|
||||||
|
// 在事务中立即保存更改
|
||||||
|
return tx.Save(uf).Error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteUploadingFile(id uint) error {
|
func DeleteUploadingFile(id uint) error {
|
||||||
@@ -135,3 +143,18 @@ func UpdateFile(id uint, filename string, description string) (*model.File, erro
|
|||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetFileStorageKey(id uint, storageKey string) error {
|
||||||
|
f := &model.File{}
|
||||||
|
if err := db.Where("id = ?", id).First(f).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.StorageKey = storageKey
|
||||||
|
if err := db.Save(f).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return model.NewNotFoundError("file not found")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -179,21 +179,19 @@ func FinishUploadingFile(uid uint, fid uint) (*model.FileView, error) {
|
|||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
|
||||||
_ = os.Remove(resultFilePath)
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i := 0; i < uploadingFile.BlocksCount(); i++ {
|
for i := 0; i < uploadingFile.BlocksCount(); i++ {
|
||||||
blockPath := filepath.Join(uploadingFile.TempPath, strconv.Itoa(i))
|
blockPath := filepath.Join(uploadingFile.TempPath, strconv.Itoa(i))
|
||||||
data, err := os.ReadFile(blockPath)
|
data, err := os.ReadFile(blockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("failed to read block file: ", err)
|
log.Error("failed to read block file: ", err)
|
||||||
_ = file.Close()
|
_ = file.Close()
|
||||||
|
_ = os.Remove(resultFilePath)
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
if _, err := file.Write(data); err != nil {
|
if _, err := file.Write(data); err != nil {
|
||||||
log.Error("failed to write result file: ", err)
|
log.Error("failed to write result file: ", err)
|
||||||
_ = file.Close()
|
_ = file.Close()
|
||||||
|
_ = os.Remove(resultFilePath)
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,28 +203,41 @@ func FinishUploadingFile(uid uint, fid uint) (*model.FileView, error) {
|
|||||||
s, err := dao.GetStorage(uploadingFile.TargetStorageID)
|
s, err := dao.GetStorage(uploadingFile.TargetStorageID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("failed to get storage: ", err)
|
log.Error("failed to get storage: ", err)
|
||||||
|
_ = os.Remove(resultFilePath)
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
|
|
||||||
iStorage := storage.NewStorage(s)
|
iStorage := storage.NewStorage(s)
|
||||||
if iStorage == nil {
|
if iStorage == nil {
|
||||||
log.Error("failed to find storage: ", err)
|
log.Error("failed to find storage: ", err)
|
||||||
|
_ = os.Remove(resultFilePath)
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
|
|
||||||
storageKey, err := iStorage.Upload(resultFilePath)
|
dbFile, err := dao.CreateFile(uploadingFile.Filename, uploadingFile.Description, uploadingFile.TargetResourceID, &uploadingFile.TargetStorageID, "", "")
|
||||||
if err != nil {
|
|
||||||
log.Error("failed to upload file: ", err)
|
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
|
||||||
}
|
|
||||||
|
|
||||||
dbFile, err := dao.CreateFile(uploadingFile.Filename, uploadingFile.Description, uploadingFile.TargetResourceID, &uploadingFile.TargetStorageID, storageKey, "")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("failed to create file in db: ", err)
|
log.Error("failed to create file in db: ", err)
|
||||||
_ = iStorage.Delete(storageKey)
|
_ = os.Remove(resultFilePath)
|
||||||
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
return nil, model.NewInternalServerError("failed to finish uploading file. please re-upload")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
_ = os.Remove(resultFilePath)
|
||||||
|
}()
|
||||||
|
storageKey, err := iStorage.Upload(resultFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to upload file to storage: ", err)
|
||||||
|
} else {
|
||||||
|
err = dao.SetFileStorageKey(dbFile.ID, storageKey)
|
||||||
|
if err != nil {
|
||||||
|
_ = iStorage.Delete(storageKey)
|
||||||
|
_ = dao.DeleteFile(dbFile.ID)
|
||||||
|
log.Error("failed to set file storage key: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return dbFile.ToView(), nil
|
return dbFile.ToView(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +378,10 @@ func DownloadFile(fid uint) (string, string, error) {
|
|||||||
return "", "", model.NewInternalServerError("failed to find storage")
|
return "", "", model.NewInternalServerError("failed to find storage")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if file.StorageKey == "" {
|
||||||
|
return "", "", model.NewRequestError("file is not available, please try again later")
|
||||||
|
}
|
||||||
|
|
||||||
path, err := iStorage.Download(file.StorageKey)
|
path, err := iStorage.Download(file.StorageKey)
|
||||||
|
|
||||||
return path, file.Filename, err
|
return path, file.Filename, err
|
||||||
|
Reference in New Issue
Block a user