move on on complete upload

This commit is contained in:
celogeek 2022-05-15 00:19:45 +02:00
parent 87f2e08227
commit 0bd48fa166
Signed by: celogeek
GPG Key ID: E6B7BDCFC446233A

View File

@ -8,6 +8,7 @@ import (
"io"
"net/http"
"os"
"strings"
"time"
"github.com/gin-gonic/gin"
@ -19,10 +20,11 @@ const (
)
var (
ErrUploadNotExists = errors.New("upload id doesn't exists")
ErrUploadPartTooLarge = fmt.Errorf("upload part too large (> %d B)", MaxUploadPartSize)
ErrUploadPartWrongSha256 = errors.New("upload part wrong sha256")
ErrFileAlreadExists = errors.New("file already exists")
ErrUploadNotExists = errors.New("upload id does not exists")
ErrUploadPartTooLarge = fmt.Errorf("upload part too large (> %d B)", MaxUploadPartSize)
ErrUploadPartWrongSha256 = errors.New("upload part sha256 does not match")
ErrFileAlreadExists = errors.New("file already exists")
ErrUploadPartsCombineWrongSha256 = errors.New("upload parts combined sha256 does not match")
)
// Model
@ -71,6 +73,36 @@ type UploadCompleteRequest struct {
Parts uint `json:"parts" binding:"required"`
}
type UploadCompleteFileOptions struct {
Ext string
IsTemp bool
}
func (u *UploadCompleteRequest) Paths() []string {
return []string{u.Sha256[0:1], u.Sha256[1:2]}
}
func (u *UploadCompleteRequest) File(options *UploadCompleteFileOptions) []string {
filename := []string{}
if options == nil {
options = &UploadCompleteFileOptions{}
}
if options.IsTemp {
filename = append(filename, "._tmp_")
}
filename = append(filename, u.Sha256)
if len(options.Ext) > 0 {
filename = append(filename, ".", options.Ext)
}
return []string{
u.Sha256[0:1],
u.Sha256[1:2],
strings.Join(filename, ""),
}
}
func (s *Service) UploadPart(c *gin.Context) {
var (
upload Upload
@ -156,13 +188,52 @@ func (s *Service) UploadComplete(c *gin.Context) {
return
}
f, err := s.StorageUpload.Stat(uploadCompleteRequest.Sha256[0:1], uploadCompleteRequest.Sha256[1:2], uploadCompleteRequest.Sha256)
fmt.Println(err)
if err == nil && f.Mode().IsRegular() {
if f, err := s.StorageUpload.Stat(uploadCompleteRequest.File(nil)...); err == nil && f.Mode().IsRegular() {
c.AbortWithError(http.StatusConflict, ErrFileAlreadExists)
return
}
if err := s.StorageUpload.Create(uploadCompleteRequest.Paths()...); err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
f, err := os.Create(s.StorageUpload.Join(uploadCompleteRequest.File(&UploadCompleteFileOptions{IsTemp: true})...))
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
fsha := sha256.New()
ft := io.MultiWriter(f, fsha)
defer f.Close()
for part := uint(1); part <= uploadCompleteRequest.Parts; part++ {
p, err := os.Open(s.StorageTmp.Join(upload.Id, fmt.Sprint(part)))
if err != nil {
c.AbortWithError(http.StatusNotFound, fmt.Errorf("upload part %d missing", part))
return
}
_, err = io.Copy(ft, p)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
}
if uploadCompleteRequest.Sha256 != hex.EncodeToString(fsha.Sum(nil)) {
c.AbortWithError(http.StatusExpectationFailed, ErrUploadPartsCombineWrongSha256)
return
}
f.Close()
if err := os.Rename(
s.StorageUpload.Join(uploadCompleteRequest.File(&UploadCompleteFileOptions{IsTemp: true})...),
s.StorageUpload.Join(uploadCompleteRequest.File(nil)...),
); err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.Status(http.StatusNoContent)
}