disable file
This commit is contained in:
parent
2d1fdc1314
commit
44f0cf68be
@ -35,7 +35,6 @@ func (s *Service) Migrate() {
|
||||
tx.AutoMigrate(&Account{})
|
||||
tx.AutoMigrate(&Session{})
|
||||
tx.AutoMigrate(&File{})
|
||||
tx.AutoMigrate(&FileChunk{})
|
||||
}
|
||||
|
||||
func (s *Service) DBConnect() {
|
||||
|
@ -1,19 +1,7 @@
|
||||
package photosapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dsoprea/go-exif/v3"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jackc/pgconn"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Error
|
||||
@ -29,252 +17,252 @@ var (
|
||||
ErrStoreMissingName = errors.New("name required")
|
||||
)
|
||||
|
||||
// Service
|
||||
var CHUNK_SIZE int64 = 4 << 20
|
||||
// // Service
|
||||
// var CHUNK_SIZE int64 = 4 << 20
|
||||
|
||||
type FileRequest struct {
|
||||
Name string `json:"name"`
|
||||
Checksum string `json:"checksum"`
|
||||
Chunks []string `json:"chunks"`
|
||||
}
|
||||
// type FileRequest struct {
|
||||
// Name string `json:"name"`
|
||||
// Checksum string `json:"checksum"`
|
||||
// Chunks []string `json:"chunks"`
|
||||
// }
|
||||
|
||||
func (s *Service) FileCreate(c *gin.Context) {
|
||||
file := &FileRequest{}
|
||||
if c.BindJSON(file) != nil {
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileCreate(c *gin.Context) {
|
||||
// file := &FileRequest{}
|
||||
// if c.BindJSON(file) != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
if len(file.Name) < 1 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreMissingName)
|
||||
return
|
||||
}
|
||||
// if len(file.Name) < 1 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreMissingName)
|
||||
// return
|
||||
// }
|
||||
|
||||
if len(file.Checksum) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
if len(file.Chunks) == 0 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreMissingChunks)
|
||||
return
|
||||
}
|
||||
// if len(file.Checksum) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
// if len(file.Chunks) == 0 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreMissingChunks)
|
||||
// return
|
||||
// }
|
||||
|
||||
for _, chunk := range file.Chunks {
|
||||
if len(chunk) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
}
|
||||
// for _, chunk := range file.Chunks {
|
||||
// if len(chunk) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
r, rs, err := s.Store.Combine(file.Chunks)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "chunk") && strings.HasSuffix(err.Error(), "doesn't exists") {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
} else {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// r, rs, err := s.Store.Combine(file.Chunks)
|
||||
// if err != nil {
|
||||
// if strings.HasPrefix(err.Error(), "chunk") && strings.HasSuffix(err.Error(), "doesn't exists") {
|
||||
// c.AbortWithError(http.StatusBadRequest, err)
|
||||
// } else {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
if r != file.Checksum {
|
||||
c.AbortWithError(http.StatusExpectationFailed, ErrStoreMismatchChecksum)
|
||||
return
|
||||
}
|
||||
// if r != file.Checksum {
|
||||
// c.AbortWithError(http.StatusExpectationFailed, ErrStoreMismatchChecksum)
|
||||
// return
|
||||
// }
|
||||
|
||||
sess := s.CurrentSession(c)
|
||||
// sess := s.CurrentSession(c)
|
||||
|
||||
f := &File{
|
||||
Name: file.Name,
|
||||
Checksum: file.Checksum,
|
||||
Size: rs,
|
||||
AuthorId: &sess.AccountId,
|
||||
}
|
||||
// f := &File{
|
||||
// Name: file.Name,
|
||||
// Checksum: file.Checksum,
|
||||
// Size: rs,
|
||||
// AuthorId: &sess.AccountId,
|
||||
// }
|
||||
|
||||
err = s.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Create(f).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for i, chunk := range file.Chunks {
|
||||
fc := &FileChunk{
|
||||
FileId: f.ID,
|
||||
Part: uint32(i + 1),
|
||||
Checksum: chunk,
|
||||
}
|
||||
if err := tx.Create(fc).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
// err = s.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// if err := tx.Create(f).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for i, chunk := range file.Chunks {
|
||||
// fc := &FileChunk{
|
||||
// FileId: f.ID,
|
||||
// Part: uint32(i + 1),
|
||||
// Checksum: chunk,
|
||||
// }
|
||||
// if err := tx.Create(fc).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// })
|
||||
|
||||
if nerr, ok := err.(*pgconn.PgError); ok {
|
||||
if nerr.Code == "23505" && nerr.Detail == fmt.Sprintf("Key (checksum)=(%s) already exists.", file.Checksum) {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
// if nerr, ok := err.(*pgconn.PgError); ok {
|
||||
// if nerr.Code == "23505" && nerr.Detail == fmt.Sprintf("Key (checksum)=(%s) already exists.", file.Checksum) {
|
||||
// err = nil
|
||||
// }
|
||||
// }
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
// if err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"sum": file.Checksum,
|
||||
"nbChunks": len(file.Chunks),
|
||||
"size": rs,
|
||||
})
|
||||
}
|
||||
// c.JSON(http.StatusOK, gin.H{
|
||||
// "sum": file.Checksum,
|
||||
// "nbChunks": len(file.Chunks),
|
||||
// "size": rs,
|
||||
// })
|
||||
// }
|
||||
|
||||
func (s *Service) FileCreateChunk(c *gin.Context) {
|
||||
if c.Request.ContentLength > CHUNK_SIZE {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChunkSize)
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileCreateChunk(c *gin.Context) {
|
||||
// if c.Request.ContentLength > CHUNK_SIZE {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChunkSize)
|
||||
// return
|
||||
// }
|
||||
|
||||
b := bytes.NewBuffer([]byte{})
|
||||
io.Copy(b, c.Request.Body)
|
||||
// b := bytes.NewBuffer([]byte{})
|
||||
// io.Copy(b, c.Request.Body)
|
||||
|
||||
sess := s.CurrentSession(c)
|
||||
// sess := s.CurrentSession(c)
|
||||
|
||||
chunk := s.Store.NewChunk(b.Bytes())
|
||||
if err := chunk.Save(sess.Account.Login); err != nil {
|
||||
if errors.Is(err, ErrStoreChunkAlreadyExists) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"checksum": chunk.Sum,
|
||||
})
|
||||
} else {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// chunk := s.Store.NewChunk(b.Bytes())
|
||||
// if err := chunk.Save(sess.Account.Login); err != nil {
|
||||
// if errors.Is(err, ErrStoreChunkAlreadyExists) {
|
||||
// c.JSON(http.StatusOK, gin.H{
|
||||
// "checksum": chunk.Sum,
|
||||
// })
|
||||
// } else {
|
||||
// c.AbortWithError(http.StatusBadRequest, err)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"checksum": chunk.Sum,
|
||||
})
|
||||
}
|
||||
// c.JSON(http.StatusOK, gin.H{
|
||||
// "checksum": chunk.Sum,
|
||||
// })
|
||||
// }
|
||||
|
||||
func (s *Service) FileChunkExists(c *gin.Context) {
|
||||
checksum := c.Param("checksum")
|
||||
if len(checksum) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileChunkExists(c *gin.Context) {
|
||||
// checksum := c.Param("checksum")
|
||||
// if len(checksum) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
|
||||
if s.Store.Chunk(checksum).FileExists() {
|
||||
c.Status(http.StatusOK)
|
||||
} else {
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
// if s.Store.Chunk(checksum).FileExists() {
|
||||
// c.Status(http.StatusOK)
|
||||
// } else {
|
||||
// c.Status(http.StatusNotFound)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (s *Service) FileExists(c *gin.Context) {
|
||||
checksum := c.Param("checksum")
|
||||
if len(checksum) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileExists(c *gin.Context) {
|
||||
// checksum := c.Param("checksum")
|
||||
// if len(checksum) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
|
||||
var fileExists int64
|
||||
if err := s.DB.Model(&File{}).Where("checksum = ?", checksum).Count(&fileExists).Error; err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
// var fileExists int64
|
||||
// if err := s.DB.Model(&File{}).Where("checksum = ?", checksum).Count(&fileExists).Error; err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
if fileExists > 0 {
|
||||
c.Status(http.StatusOK)
|
||||
} else {
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
// if fileExists > 0 {
|
||||
// c.Status(http.StatusOK)
|
||||
// } else {
|
||||
// c.Status(http.StatusNotFound)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (s *Service) FileGet(c *gin.Context) {
|
||||
checksum := c.Param("checksum")
|
||||
if len(checksum) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
if checksum == c.GetHeader("If-None-Match") {
|
||||
c.Status(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileGet(c *gin.Context) {
|
||||
// checksum := c.Param("checksum")
|
||||
// if len(checksum) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
// if checksum == c.GetHeader("If-None-Match") {
|
||||
// c.Status(http.StatusNotModified)
|
||||
// return
|
||||
// }
|
||||
|
||||
f := &File{}
|
||||
if err := s.DB.Debug().Preload("Chunks").Where("checksum = ?", checksum).First(&f).Error; err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
// f := &File{}
|
||||
// if err := s.DB.Debug().Preload("Chunks").Where("checksum = ?", checksum).First(&f).Error; err != nil {
|
||||
// c.AbortWithError(http.StatusBadRequest, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
chunks := make([]string, len(f.Chunks))
|
||||
for _, fc := range f.Chunks {
|
||||
chunks[fc.Part-1] = fc.Checksum
|
||||
}
|
||||
// chunks := make([]string, len(f.Chunks))
|
||||
// for _, fc := range f.Chunks {
|
||||
// chunks[fc.Part-1] = fc.Checksum
|
||||
// }
|
||||
|
||||
reader, err := s.Store.NewStoreReader(chunks)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
// reader, err := s.Store.NewStoreReader(chunks)
|
||||
// if err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
// defer reader.Close()
|
||||
|
||||
c.DataFromReader(
|
||||
http.StatusOK,
|
||||
reader.Size,
|
||||
mime.TypeByExtension(filepath.Ext(f.Name)),
|
||||
reader,
|
||||
map[string]string{
|
||||
"Content-Disposition": fmt.Sprintf("inline; filename=\"%s\"", f.Name),
|
||||
"ETag": f.Checksum,
|
||||
},
|
||||
)
|
||||
}
|
||||
// c.DataFromReader(
|
||||
// http.StatusOK,
|
||||
// reader.Size,
|
||||
// mime.TypeByExtension(filepath.Ext(f.Name)),
|
||||
// reader,
|
||||
// map[string]string{
|
||||
// "Content-Disposition": fmt.Sprintf("inline; filename=\"%s\"", f.Name),
|
||||
// "ETag": f.Checksum,
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
|
||||
func (s *Service) FileAnalyze(c *gin.Context) {
|
||||
checksum := c.Param("checksum")
|
||||
if len(checksum) != 40 {
|
||||
c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
return
|
||||
}
|
||||
// func (s *Service) FileAnalyze(c *gin.Context) {
|
||||
// checksum := c.Param("checksum")
|
||||
// if len(checksum) != 40 {
|
||||
// c.AbortWithError(http.StatusBadRequest, ErrStoreBadChecksum)
|
||||
// return
|
||||
// }
|
||||
|
||||
f := &File{}
|
||||
if err := s.DB.Debug().Preload("Chunks").Where("checksum = ?", checksum).First(&f).Error; err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
// f := &File{}
|
||||
// if err := s.DB.Debug().Preload("Chunks").Where("checksum = ?", checksum).First(&f).Error; err != nil {
|
||||
// c.AbortWithError(http.StatusBadRequest, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
chunks := make([]string, len(f.Chunks))
|
||||
for _, fc := range f.Chunks {
|
||||
chunks[fc.Part-1] = fc.Checksum
|
||||
}
|
||||
// chunks := make([]string, len(f.Chunks))
|
||||
// for _, fc := range f.Chunks {
|
||||
// chunks[fc.Part-1] = fc.Checksum
|
||||
// }
|
||||
|
||||
reader, err := s.Store.NewStoreReader(chunks)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
// reader, err := s.Store.NewStoreReader(chunks)
|
||||
// if err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
// defer reader.Close()
|
||||
|
||||
rawExif, err := exif.SearchAndExtractExifWithReader(reader)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
entries, _, err := exif.GetFlatExifDataUniversalSearch(rawExif, nil, true)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
// rawExif, err := exif.SearchAndExtractExifWithReader(reader)
|
||||
// if err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
// entries, _, err := exif.GetFlatExifDataUniversalSearch(rawExif, nil, true)
|
||||
// if err != nil {
|
||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"exif": entries,
|
||||
})
|
||||
}
|
||||
// c.JSON(http.StatusOK, gin.H{
|
||||
// "exif": entries,
|
||||
// })
|
||||
// }
|
||||
|
||||
func (s *Service) FileInit() {
|
||||
file := s.Gin.Group("/file")
|
||||
file.Use(s.RequireSession)
|
||||
file.POST("", s.FileCreate)
|
||||
file.HEAD("/:checksum", s.FileExists)
|
||||
file.GET("/:checksum", s.FileGet)
|
||||
file.POST("/chunk", s.FileCreateChunk)
|
||||
file.HEAD("/chunk/:checksum", s.FileChunkExists)
|
||||
file.GET("/analyze/:checksum", s.FileAnalyze)
|
||||
// file.POST("", s.FileCreate)
|
||||
// file.HEAD("/:checksum", s.FileExists)
|
||||
// file.GET("/:checksum", s.FileGet)
|
||||
// file.POST("/chunk", s.FileCreateChunk)
|
||||
// file.HEAD("/chunk/:checksum", s.FileChunkExists)
|
||||
// file.GET("/analyze/:checksum", s.FileAnalyze)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user