подготовка для cli + api

This commit is contained in:
Anatoly Prohacky 2023-04-28 09:35:30 +10:00
parent deb168b2e1
commit d3397d8e4c
3 changed files with 124 additions and 48 deletions

View File

@ -1,24 +1,32 @@
package handler package file
import ( import (
"bytes"
"encoding/json"
"errors" "errors"
"net/http" "net/http"
"strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/xuri/excelize/v2" "github.com/sirupsen/logrus"
"gitstore.ru/tolikproh/sirius/internal/model" "gitstore.ru/tolikproh/sirius/internal/model"
"gitstore.ru/tolikproh/sirius/internal/service"
) )
type Handler struct {
log *logrus.Logger
cfg *model.Config
}
var ( var (
TEXT_TYPES = map[string]interface{}{ TEXT_TYPES = map[string]interface{}{
"text/plain; charset=utf-8": nil, "text/plain; charset=utf-8": nil,
} }
) )
func New(cfg *model.Config, log *logrus.Logger) *Handler {
// HTTP Server
return &Handler{cfg: cfg, log: log}
}
func (s *Handler) GinConvert(c *gin.Context) { func (s *Handler) GinConvert(c *gin.Context) {
sessionId := uuid.New().String() sessionId := uuid.New().String()
@ -40,8 +48,6 @@ func (s *Handler) GinConvert(c *gin.Context) {
buffer := make([]byte, fileHeader.Size) buffer := make([]byte, fileHeader.Size)
file.Read(buffer) file.Read(buffer)
buffer = bytes.TrimPrefix(buffer, []byte("\xef\xbb\xbf"))
fileType := http.DetectContentType(buffer) fileType := http.DetectContentType(buffer)
// Validate File Type // Validate File Type
@ -53,55 +59,17 @@ func (s *Handler) GinConvert(c *gin.Context) {
return return
} }
if !json.Valid(buffer) { respBuff, err := service.SiriusConv(buffer)
s.log.Errorf("session id: %s. error code: 003. formated data not json", sessionId)
c.JSON(http.StatusBadRequest, gin.H{
"error": errors.New("formated data not json").Error(),
})
return
}
var sirius model.Sirius
err = json.Unmarshal(buffer, &sirius)
if err != nil { if err != nil {
s.log.Errorf("session id: %s. error code: 004. %s", sessionId, err.Error()) s.log.Errorf("session id: %s. error code: 004. %s", sessionId, err.Error())
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": errors.New("Error unmarshal file").Error(), "error": err.Error(),
}) })
return return
} }
buff, err := SaveToExel(sirius.NewBolid().ZoneInfo()) c.Data(200, "application/vnd.ms-excel", respBuff.Bytes())
if err != nil {
s.log.Errorf("session id: %s. error code: 005. %s", sessionId, err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": errors.New("Error create file").Error(),
})
return
}
c.Data(200, "application/vnd.ms-excel", buff.Bytes())
s.log.Printf("session id: %s.converted: ok. filename: %s; file size: %d bytes", sessionId, fileHeader.Filename, fileHeader.Size) s.log.Printf("session id: %s.converted: ok. filename: %s; file size: %d bytes", sessionId, fileHeader.Filename, fileHeader.Size)
} }
func SaveToExel(data []model.ZoneInfo) (*bytes.Buffer, error) {
f := excelize.NewFile()
defer f.Close()
// Create a new sheet.
f.SetCellValue("Sheet1", "A2", "№ зоны")
f.SetCellValue("Sheet1", "B2", "Описание зоны")
f.SetCellValue("Sheet1", "C2", "Адреса в зоне")
i := 3
for _, d := range data {
f.SetCellValue("Sheet1", "A"+strconv.Itoa(i), d.ZoneNum)
f.SetCellValue("Sheet1", "B"+strconv.Itoa(i), d.ZoneName)
f.SetCellValue("Sheet1", "C"+strconv.Itoa(i), d.InputString())
i++
}
return f.WriteToBuffer()
}

View File

@ -1,8 +1,14 @@
package handler package handler
import ( import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gitstore.ru/tolikproh/sirius/internal/model" "gitstore.ru/tolikproh/sirius/internal/model"
"gitstore.ru/tolikproh/sirius/internal/service"
) )
type Handler struct { type Handler struct {
@ -10,7 +16,60 @@ type Handler struct {
cfg *model.Config cfg *model.Config
} }
var (
TEXT_TYPES = map[string]interface{}{
"text/plain; charset=utf-8": nil,
}
)
func New(cfg *model.Config, log *logrus.Logger) *Handler { func New(cfg *model.Config, log *logrus.Logger) *Handler {
// HTTP Server // HTTP Server
return &Handler{cfg: cfg, log: log} return &Handler{cfg: cfg, log: log}
} }
func (s *Handler) GinConvert(c *gin.Context) {
sessionId := uuid.New().String()
s.log.Printf("start convert. session id: %s; user agent: %s; remote addr: %s; file size [byte]: %d",
sessionId, c.Request.UserAgent(), c.Request.RemoteAddr, c.Request.ContentLength)
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, s.cfg.Srv.MaxSizeFile<<20)
file, fileHeader, err := c.Request.FormFile("file")
if err != nil {
s.log.Errorf("session id: %s. error code: 001. %s", sessionId, err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
defer file.Close()
buffer := make([]byte, fileHeader.Size)
file.Read(buffer)
fileType := http.DetectContentType(buffer)
// Validate File Type
if _, ex := TEXT_TYPES[fileType]; !ex {
s.log.Errorf("session id: %s. error code: 002. formated data not text/plain", sessionId)
c.JSON(http.StatusBadRequest, gin.H{
"error": errors.New("formated data not text/plain").Error(),
})
return
}
respBuff, err := service.SiriusConv(buffer)
if err != nil {
s.log.Errorf("session id: %s. error code: 004. %s", sessionId, err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.Data(200, "application/vnd.ms-excel", respBuff.Bytes())
s.log.Printf("session id: %s.converted: ok. filename: %s; file size: %d bytes", sessionId, fileHeader.Filename, fileHeader.Size)
}

View File

@ -0,0 +1,49 @@
package service
import (
"bytes"
"encoding/json"
"errors"
"strconv"
"github.com/xuri/excelize/v2"
"gitstore.ru/tolikproh/sirius/internal/model"
)
func SiriusConv(data []byte) (*bytes.Buffer, error) {
data = bytes.TrimPrefix(data, []byte("\xef\xbb\xbf"))
if !json.Valid(data) {
return nil, errors.New("formated data not json")
}
var sirius model.Sirius
err := json.Unmarshal(data, &sirius)
if err != nil {
return nil, errors.New("Error unmarshal file")
}
return SaveToExel(sirius.NewBolid().ZoneInfo())
}
func SaveToExel(data []model.ZoneInfo) (*bytes.Buffer, error) {
f := excelize.NewFile()
defer f.Close()
// Create a new sheet.
f.SetCellValue("Sheet1", "A2", "№ зоны")
f.SetCellValue("Sheet1", "B2", "Описание зоны")
f.SetCellValue("Sheet1", "C2", "Адреса в зоне")
i := 3
for _, d := range data {
f.SetCellValue("Sheet1", "A"+strconv.Itoa(i), d.ZoneNum)
f.SetCellValue("Sheet1", "B"+strconv.Itoa(i), d.ZoneName)
f.SetCellValue("Sheet1", "C"+strconv.Itoa(i), d.InputString())
i++
}
return f.WriteToBuffer()
}