Add admin panel: visit counter, product editor, screenshots upload
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var allowedTypes = map[string]string{
|
||||
"image/jpeg": ".jpg",
|
||||
"image/png": ".png",
|
||||
"image/webp": ".webp",
|
||||
"image/gif": ".gif",
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
RootDir string
|
||||
}
|
||||
|
||||
func NewStorage(root string) (*Storage, error) {
|
||||
if err := os.MkdirAll(root, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Storage{RootDir: root}, nil
|
||||
}
|
||||
|
||||
func (s *Storage) SaveProductImage(productID int, file multipart.File, header *multipart.FileHeader) (string, error) {
|
||||
buf := make([]byte, 512)
|
||||
n, err := file.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
contentType := http.DetectContentType(buf[:n])
|
||||
ext, ok := allowedTypes[contentType]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("недопустимый тип файла: %s", contentType)
|
||||
}
|
||||
|
||||
if _, err := file.Seek(0, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dir := filepath.Join(s.RootDir, "products", fmt.Sprintf("%d", productID))
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
name := uuid.New().String() + ext
|
||||
fullPath := filepath.Join(dir, name)
|
||||
|
||||
dst, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, io.MultiReader(bytes.NewReader(buf[:n]), file)); err != nil {
|
||||
os.Remove(fullPath)
|
||||
return "", err
|
||||
}
|
||||
|
||||
webPath := "/uploads/products/" + fmt.Sprintf("%d", productID) + "/" + name
|
||||
_ = header
|
||||
return webPath, nil
|
||||
}
|
||||
|
||||
func (s *Storage) Remove(webPath string) error {
|
||||
if !strings.HasPrefix(webPath, "/uploads/") {
|
||||
return nil
|
||||
}
|
||||
rel := strings.TrimPrefix(webPath, "/uploads/")
|
||||
full := filepath.Join(s.RootDir, rel)
|
||||
return os.Remove(full)
|
||||
}
|
||||
|
||||
func (s *Storage) FileServer() http.Handler {
|
||||
return http.StripPrefix("/uploads/", http.FileServer(http.Dir(s.RootDir)))
|
||||
}
|
||||
Reference in New Issue
Block a user