feat: add feature upload file coverimage in article

This commit is contained in:
pahmiudahgede 2025-02-08 03:54:36 +07:00
parent 76bd158b55
commit fc1298e894
4 changed files with 63 additions and 21 deletions

1
.gitignore vendored
View File

@ -28,3 +28,4 @@ go.work.sum
# Ignore avatar images
/public/uploads/avatars/
/public/uploads/articles/

View File

@ -29,9 +29,7 @@ func (r *RequestArticleDTO) Validate() (map[string][]string, bool) {
if strings.TrimSpace(r.Title) == "" {
errors["title"] = append(errors["title"], "Title is required")
}
if strings.TrimSpace(r.CoverImage) == "" {
errors["coverImage"] = append(errors["coverImage"], "Cover image is required")
}
if strings.TrimSpace(r.Author) == "" {
errors["author"] = append(errors["author"], "Author is required")
}

View File

@ -18,22 +18,28 @@ func NewArticleHandler(articleService services.ArticleService) *ArticleHandler {
}
func (h *ArticleHandler) CreateArticle(c *fiber.Ctx) error {
var requestArticleDTO dto.RequestArticleDTO
if err := c.BodyParser(&requestArticleDTO); err != nil {
var request dto.RequestArticleDTO
if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
}
errors, valid := requestArticleDTO.Validate()
errors, valid := request.Validate()
if !valid {
return utils.ValidationErrorResponse(c, errors)
}
articleResponse, err := h.ArticleService.CreateArticle(requestArticleDTO)
coverImage, err := c.FormFile("coverImage")
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusBadRequest, err.Error())
return utils.GenericErrorResponse(c, fiber.StatusBadRequest, "Cover image is required")
}
return utils.CreateResponse(c, articleResponse, "Article created successfully")
articleResponse, err := h.ArticleService.CreateArticle(request, coverImage)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, err.Error())
}
return utils.SuccessResponse(c, articleResponse, "Article created successfully")
}
func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {

View File

@ -2,8 +2,12 @@ package services
import (
"fmt"
"mime/multipart"
"os"
"path/filepath"
"time"
"github.com/google/uuid"
"github.com/pahmiudahgede/senggoldong/dto"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/model"
@ -11,7 +15,7 @@ import (
)
type ArticleService interface {
CreateArticle(articleDTO dto.RequestArticleDTO) (*dto.ArticleResponseDTO, error)
CreateArticle(request dto.RequestArticleDTO, coverImage *multipart.FileHeader) (*dto.ArticleResponseDTO, error)
GetAllArticles(page, limit int) ([]dto.ArticleResponseDTO, int, error)
GetArticleByID(id string) (*dto.ArticleResponseDTO, error)
}
@ -24,22 +28,55 @@ func NewArticleService(articleRepo repositories.ArticleRepository) ArticleServic
return &articleService{ArticleRepo: articleRepo}
}
func (s *articleService) CreateArticle(articleDTO dto.RequestArticleDTO) (*dto.ArticleResponseDTO, error) {
func (s *articleService) CreateArticle(request dto.RequestArticleDTO, coverImage *multipart.FileHeader) (*dto.ArticleResponseDTO, error) {
article := &model.Article{
Title: articleDTO.Title,
CoverImage: articleDTO.CoverImage,
Author: articleDTO.Author,
Heading: articleDTO.Heading,
Content: articleDTO.Content,
coverImageDir := "./public/uploads/articles"
if _, err := os.Stat(coverImageDir); os.IsNotExist(err) {
err := os.MkdirAll(coverImageDir, os.ModePerm)
if err != nil {
return nil, fmt.Errorf("failed to create directory for cover image: %v", err)
}
}
err := s.ArticleRepo.CreateArticle(article)
extension := filepath.Ext(coverImage.Filename)
if extension != ".jpg" && extension != ".jpeg" && extension != ".png" {
return nil, fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
}
coverImageFileName := fmt.Sprintf("%s_cover%s", uuid.New().String(), extension)
coverImagePath := filepath.Join(coverImageDir, coverImageFileName)
src, err := coverImage.Open()
if err != nil {
return nil, fmt.Errorf("failed to open uploaded file: %v", err)
}
defer src.Close()
dst, err := os.Create(coverImagePath)
if err != nil {
return nil, fmt.Errorf("failed to create cover image file: %v", err)
}
defer dst.Close()
_, err = dst.ReadFrom(src)
if err != nil {
return nil, fmt.Errorf("failed to save cover image: %v", err)
}
article := model.Article{
Title: request.Title,
CoverImage: coverImagePath,
Author: request.Author,
Heading: request.Heading,
Content: request.Content,
}
err = s.ArticleRepo.CreateArticle(&article)
if err != nil {
return nil, fmt.Errorf("failed to create article: %v", err)
}
publishedAt, _ := utils.FormatDateToIndonesianFormat(article.PublishedAt)
createdAt, _ := utils.FormatDateToIndonesianFormat(article.PublishedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(article.UpdatedAt)
articleResponseDTO := &dto.ArticleResponseDTO{
@ -49,7 +86,7 @@ func (s *articleService) CreateArticle(articleDTO dto.RequestArticleDTO) (*dto.A
Author: article.Author,
Heading: article.Heading,
Content: article.Content,
PublishedAt: publishedAt,
PublishedAt: createdAt,
UpdatedAt: updatedAt,
}