move on on complete upload
This commit is contained in:
parent
87f2e08227
commit
0bd48fa166
@ -8,6 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -19,10 +20,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrUploadNotExists = errors.New("upload id doesn't exists")
|
ErrUploadNotExists = errors.New("upload id does not exists")
|
||||||
ErrUploadPartTooLarge = fmt.Errorf("upload part too large (> %d B)", MaxUploadPartSize)
|
ErrUploadPartTooLarge = fmt.Errorf("upload part too large (> %d B)", MaxUploadPartSize)
|
||||||
ErrUploadPartWrongSha256 = errors.New("upload part wrong sha256")
|
ErrUploadPartWrongSha256 = errors.New("upload part sha256 does not match")
|
||||||
ErrFileAlreadExists = errors.New("file already exists")
|
ErrFileAlreadExists = errors.New("file already exists")
|
||||||
|
ErrUploadPartsCombineWrongSha256 = errors.New("upload parts combined sha256 does not match")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Model
|
// Model
|
||||||
@ -71,6 +73,36 @@ type UploadCompleteRequest struct {
|
|||||||
Parts uint `json:"parts" binding:"required"`
|
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) {
|
func (s *Service) UploadPart(c *gin.Context) {
|
||||||
var (
|
var (
|
||||||
upload Upload
|
upload Upload
|
||||||
@ -156,13 +188,52 @@ func (s *Service) UploadComplete(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := s.StorageUpload.Stat(uploadCompleteRequest.Sha256[0:1], uploadCompleteRequest.Sha256[1:2], uploadCompleteRequest.Sha256)
|
if f, err := s.StorageUpload.Stat(uploadCompleteRequest.File(nil)...); err == nil && f.Mode().IsRegular() {
|
||||||
fmt.Println(err)
|
|
||||||
if err == nil && f.Mode().IsRegular() {
|
|
||||||
c.AbortWithError(http.StatusConflict, ErrFileAlreadExists)
|
c.AbortWithError(http.StatusConflict, ErrFileAlreadExists)
|
||||||
return
|
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)
|
c.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user