upload chunks
This commit is contained in:
parent
c123051dd0
commit
1c5b200151
@ -4,10 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -24,10 +28,83 @@ func (s *Service) PrepareStore() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) StoreDir(checksum string) (string, error) {
|
||||||
|
dir := filepath.Join(s.Config.StorePath, "original", checksum[0:0], checksum[1:1], checksum[2:])
|
||||||
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
return dir, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) TempDir(checksum string) (string, error) {
|
||||||
|
dir := filepath.Join(s.Config.StorePath, "tmp", checksum)
|
||||||
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
return dir, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileChunks struct {
|
||||||
|
N uint64
|
||||||
|
Path fs.FS
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) FileChunks(checksum string) ([]FileChunks, error) {
|
||||||
|
base := filepath.Join(s.Config.StorePath, "tmp", checksum)
|
||||||
|
baseDir := os.DirFS(base)
|
||||||
|
dir, err := os.Open(base)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer dir.Close()
|
||||||
|
|
||||||
|
files, err := dir.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parts := []FileChunks{}
|
||||||
|
for _, f := range files {
|
||||||
|
n, err := strconv.ParseUint(f, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts = append(parts, FileChunks{n, baseDir, f})
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(parts, func(i, j int) bool {
|
||||||
|
return parts[i].N < parts[j].N
|
||||||
|
})
|
||||||
|
return parts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) FileCreate(c *gin.Context) {
|
func (s *Service) FileCreate(c *gin.Context) {
|
||||||
var originalChecksum = c.Param("original_checksum")
|
var originalChecksum = c.Param("original_checksum")
|
||||||
|
files, err := s.FileChunks(originalChecksum)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(c, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := sha1.New()
|
||||||
|
size := uint64(0)
|
||||||
|
for _, f := range files {
|
||||||
|
b, err := fs.ReadFile(f.Path, f.Name)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(c, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sum.Write(b)
|
||||||
|
size += uint64(len(b))
|
||||||
|
}
|
||||||
|
r := hex.EncodeToString(sum.Sum(nil))
|
||||||
|
if r != originalChecksum {
|
||||||
|
fmt.Printf("R=%s, O=%s\n", r, originalChecksum)
|
||||||
|
s.Error(c, http.StatusExpectationFailed, ErrStoreMismatchChecksum)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"original_checksum": originalChecksum,
|
"status": "success",
|
||||||
|
"checksum": originalChecksum,
|
||||||
|
"nbParts": len(files),
|
||||||
|
"size": size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,18 +124,16 @@ func (s *Service) FileChunk(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p, err := strconv.ParseUint(part, 10, 64)
|
||||||
|
if err != nil || p < 1 {
|
||||||
|
s.Error(c, http.StatusBadRequest, ErrStoreBadPartNumber)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
b := bytes.NewBuffer([]byte{})
|
b := bytes.NewBuffer([]byte{})
|
||||||
io.Copy(b, c.Request.Body)
|
io.Copy(b, c.Request.Body)
|
||||||
c.Request.Body.Close()
|
c.Request.Body.Close()
|
||||||
|
|
||||||
f, err := os.Create(filepath.Join(s.Config.StorePath, "test"))
|
|
||||||
if err != nil {
|
|
||||||
s.Error(c, http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f.Write(b.Bytes())
|
|
||||||
f.Close()
|
|
||||||
|
|
||||||
sum := sha1.New()
|
sum := sha1.New()
|
||||||
sum.Write(b.Bytes())
|
sum.Write(b.Bytes())
|
||||||
r := hex.EncodeToString(sum.Sum(nil))
|
r := hex.EncodeToString(sum.Sum(nil))
|
||||||
@ -68,13 +143,21 @@ func (s *Service) FileChunk(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir, err := s.TempDir(originalChecksum)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(c, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(filepath.Join(dir, part))
|
||||||
|
if err != nil {
|
||||||
|
s.Error(c, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.Write(b.Bytes())
|
||||||
|
f.Close()
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"original_checksum": originalChecksum,
|
"status": "success",
|
||||||
"part": part,
|
|
||||||
"part_checksum": partChecksum,
|
|
||||||
"body": gin.H{
|
|
||||||
"checksum": r,
|
|
||||||
"size": b.Len(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user