113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/disintegration/imaging"
|
||
|
"github.com/knadh/listmonk/models"
|
||
|
"github.com/labstack/echo"
|
||
|
uuid "github.com/satori/go.uuid"
|
||
|
)
|
||
|
|
||
|
var imageMimes = []string{"image/jpg", "image/jpeg", "image/png", "image/svg", "image/gif"}
|
||
|
|
||
|
const (
|
||
|
thumbPrefix = "thumb_"
|
||
|
thumbWidth = 90
|
||
|
thumbHeight = 90
|
||
|
)
|
||
|
|
||
|
// handleUploadMedia handles media file uploads.
|
||
|
func handleUploadMedia(c echo.Context) error {
|
||
|
var (
|
||
|
app = c.Get("app").(*App)
|
||
|
cleanUp = false
|
||
|
)
|
||
|
|
||
|
// Upload the file.
|
||
|
fName, err := uploadFile("file", app.Constants.UploadPath, "", imageMimes, c)
|
||
|
if err != nil {
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error uploading file: %s", err))
|
||
|
}
|
||
|
path := filepath.Join(app.Constants.UploadPath, fName)
|
||
|
|
||
|
defer func() {
|
||
|
// If any of the subroutines in this function fail,
|
||
|
// the uploaded image should be removed.
|
||
|
if cleanUp {
|
||
|
os.Remove(path)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
// Create a thumbnail.
|
||
|
src, err := imaging.Open(path)
|
||
|
if err != nil {
|
||
|
cleanUp = true
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error opening image for resizing: %s", err))
|
||
|
}
|
||
|
|
||
|
t := imaging.Resize(src, thumbWidth, 0, imaging.Lanczos)
|
||
|
if err := imaging.Save(t, fmt.Sprintf("%s/%s%s", app.Constants.UploadPath, thumbPrefix, fName)); err != nil {
|
||
|
cleanUp = true
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error saving thumbnail: %s", err))
|
||
|
}
|
||
|
|
||
|
// Write to the DB.
|
||
|
if _, err := app.Queries.InsertMedia.Exec(uuid.NewV4(), fName, fmt.Sprintf("%s%s", thumbPrefix, fName), 0, 0); err != nil {
|
||
|
cleanUp = true
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error saving uploaded file: %s", pqErrMsg(err)))
|
||
|
}
|
||
|
|
||
|
return c.JSON(http.StatusOK, okResp{true})
|
||
|
}
|
||
|
|
||
|
// handleGetMedia handles retrieval of uploaded media.
|
||
|
func handleGetMedia(c echo.Context) error {
|
||
|
var (
|
||
|
app = c.Get("app").(*App)
|
||
|
out []models.Media
|
||
|
)
|
||
|
|
||
|
if err := app.Queries.GetMedia.Select(&out); err != nil {
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error fetching media list: %s", pqErrMsg(err)))
|
||
|
}
|
||
|
|
||
|
for i := 0; i < len(out); i++ {
|
||
|
out[i].URI = fmt.Sprintf("%s/%s", app.Constants.UploadURI, out[i].Filename)
|
||
|
out[i].ThumbURI = fmt.Sprintf("%s/%s%s", app.Constants.UploadURI, thumbPrefix, out[i].Filename)
|
||
|
}
|
||
|
|
||
|
return c.JSON(http.StatusOK, okResp{out})
|
||
|
}
|
||
|
|
||
|
// deleteMedia handles deletion of uploaded media.
|
||
|
func handleDeleteMedia(c echo.Context) error {
|
||
|
var (
|
||
|
app = c.Get("app").(*App)
|
||
|
id, _ = strconv.Atoi(c.Param("id"))
|
||
|
)
|
||
|
|
||
|
if id < 1 {
|
||
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
|
||
|
}
|
||
|
|
||
|
var m models.Media
|
||
|
if err := app.Queries.DeleteMedia.Get(&m, id); err != nil {
|
||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||
|
fmt.Sprintf("Error deleting media: %s", pqErrMsg(err)))
|
||
|
}
|
||
|
os.Remove(filepath.Join(app.Constants.UploadPath, m.Filename))
|
||
|
os.Remove(filepath.Join(app.Constants.UploadPath, fmt.Sprintf("%s%s", thumbPrefix, m.Filename)))
|
||
|
|
||
|
return c.JSON(http.StatusOK, okResp{true})
|
||
|
}
|