Skip to content

Commit

Permalink
feat(main): call the build factory in the main package
Browse files Browse the repository at this point in the history
  • Loading branch information
danvergara committed Dec 10, 2023
1 parent 4ffe9b1 commit d76872c
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 185 deletions.
68 changes: 52 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (
"path/filepath"
"strings"

"github.com/gabriel-vasile/mimetype"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"

"github.com/danvergara/morphos/pkg/files/images"
"github.com/gabriel-vasile/mimetype"
"github.com/danvergara/morphos/pkg/files"
)

const (
Expand Down Expand Up @@ -45,11 +45,6 @@ type ConvertedFile struct {
Filename string
}

type FileFormat struct {
Name string
ID int
}

func index(w http.ResponseWriter, _ *http.Request) {
files := []string{
"templates/base.tmpl",
Expand Down Expand Up @@ -100,17 +95,39 @@ func handleUploadFile(w http.ResponseWriter, r *http.Request) {
return
}

fileType := r.FormValue("input_format")
targetFileType := r.FormValue("input_format")

detectedFileType := mimetype.Detect(fileBytes)
convertedFile, err = images.ConverImage(detectedFileType.String(), fileType, fileBytes)

fileType, subType, err := files.TypeAndSupType(detectedFileType.String())
if err != nil {
log.Printf("error ocurred while converting image %v", err)
log.Printf("error occurred getting type and subtype from mimetype: %v", err)
renderError(w, "INVALID_FILE", http.StatusBadRequest)
return
}

fileFactory, err := files.BuildFactory(fileType)
if err != nil {
log.Printf("error occurred while getting a file factory: %v", err)
renderError(w, "INVALID_FILE", http.StatusBadRequest)
return
}

f, err := fileFactory.NewFile(subType)
if err != nil {
log.Printf("error occurred getting the file object: %v", err)
renderError(w, "INVALID_FILE", http.StatusBadRequest)
return
}

convertedFileName = filename(fileHeader.Filename, fileType)
convertedFile, err = f.ConvertTo(targetFileType, fileBytes)
if err != nil {
log.Printf("error ocurred while converting image %v", err)
renderError(w, "INTERNAL_ERROR", http.StatusInternalServerError)
return
}

convertedFileName = filename(fileHeader.Filename, targetFileType)
convertedFilePath = filepath.Join(uploadPath, convertedFileName)

newFile, err := os.Create(convertedFilePath)
Expand Down Expand Up @@ -164,16 +181,35 @@ func handleFileFormat(w http.ResponseWriter, r *http.Request) {

detectedFileType := mimetype.Detect(fileBytes)

files := []string{
templates := []string{
"templates/partials/form.tmpl",
}

tmpl, err := template.ParseFS(templatesHTML, files...)
formats := images.FileFormatsToConvert(detectedFileType.String())
fileType, subType, err := files.TypeAndSupType(detectedFileType.String())
if err != nil {
log.Printf("error occurred getting type and subtype from mimetype: %v", err)
renderError(w, "INVALID_FILE", http.StatusBadRequest)
return
}

if err = tmpl.ExecuteTemplate(w, "format-elements", formats); err != nil {
fileFactory, err := files.BuildFactory(fileType)
if err != nil {
log.Printf("error occurred while getting a file factory: %v", err)
renderError(w, "INVALID_FILE", http.StatusBadRequest)
return
}

f, err := fileFactory.NewFile(subType)
if err != nil {
log.Printf("error occurred getting the file object: %v", err)
renderError(w, "INTERNAL_ERROR", http.StatusInternalServerError)
return
}

tmpl, err := template.ParseFS(templatesHTML, templates...)
if err = tmpl.ExecuteTemplate(w, "format-elements", f.SupportedFormats()); err != nil {
log.Printf("error occurred parsing template files: %v", err)
renderError(w, "FINTERNAL_ERROR", http.StatusInternalServerError)
renderError(w, "INTERNAL_ERROR", http.StatusInternalServerError)
return
}
}
Expand Down
166 changes: 0 additions & 166 deletions pkg/files/images/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package images

import (
"bytes"
"fmt"
"image"
"image/gif"
"image/jpeg"
Expand All @@ -12,7 +11,6 @@ import (
"github.com/chai2010/webp"
"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
webpx "golang.org/x/image/webp"
)

const (
Expand All @@ -27,100 +25,6 @@ const (
imageMimeType = "image/"
)

// FileFormat is the file format representation meant to be shown in the
// form template as an option.
type FileFormat struct {
// Name of the file format to be shown in the option tag and as option value.
Name string
}

// ConverImage returns a image converted as an array of bytes,
// if somethings wrong happens, the functions will error out.
// The functions receives the format from to be converted,
// the file format to be converted to and the image to be converted.
func ConverImage(from, to string, imageBytes []byte) ([]byte, error) {
var (
img image.Image
result []byte
err error
)

to = ParseMimeType(to)
from = ParseMimeType(from)

switch from {
case PNG:
img, err = png.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
case JPEG, JPG:
img, err = jpeg.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
case GIF:
img, err = gif.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
case WEBP:
img, err = webpx.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
case TIFF:
img, err = tiff.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
case BMP:
img, err = bmp.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("file format %s not supported", from)
}

switch to {
case PNG:
result, err = toPNG(img)
if err != nil {
return nil, err
}
case JPEG, JPG:
result, err = toJPG(img)
if err != nil {
return nil, err
}
case GIF:
result, err = toGIF(img)
if err != nil {
return nil, err
}
case WEBP:
result, err = toWEBP(img)
if err != nil {
return nil, err
}
case TIFF:
result, err = toTIFF(img)
if err != nil {
return nil, err
}
case BMP:
result, err = toBMP(img)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("file format to conver to %s not supported", to)
}

return result, nil
}

func toPNG(img image.Image) ([]byte, error) {
buf := new(bytes.Buffer)

Expand Down Expand Up @@ -186,76 +90,6 @@ func toBMP(img image.Image) ([]byte, error) {
return buf.Bytes(), nil
}

func FileFormatsToConvert(to string) map[string][]FileFormat {
formats := make(map[string][]FileFormat)

to = ParseMimeType(to)

switch to {
case JPEG, JPG:
formats = map[string][]FileFormat{
"Formats": {
{Name: PNG},
{Name: GIF},
{Name: WEBP},
{Name: TIFF},
{Name: BMP},
},
}
case PNG:
formats = map[string][]FileFormat{
"Formats": {
{Name: JPG},
{Name: GIF},
{Name: WEBP},
{Name: TIFF},
{Name: BMP},
},
}
case GIF:
formats = map[string][]FileFormat{
"Formats": {
{Name: JPG},
{Name: PNG},
{Name: WEBP},
{Name: TIFF},
{Name: BMP},
},
}
case WEBP:
formats = map[string][]FileFormat{
"Formats": {
{Name: JPG},
{Name: PNG},
{Name: GIF},
{Name: TIFF},
{Name: BMP},
},
}
case TIFF:
formats = map[string][]FileFormat{
"Formats": {
{Name: JPG},
{Name: PNG},
{Name: GIF},
{Name: WEBP},
{Name: BMP},
},
}
case BMP:
formats = map[string][]FileFormat{
"Formats": {
{Name: JPG},
{Name: PNG},
{Name: GIF},
{Name: WEBP},
{Name: TIFF},
},
}
}
return formats
}

func ParseMimeType(mimetype string) string {
if !strings.Contains(mimetype, imageMimeType) {
return mimetype
Expand Down
1 change: 1 addition & 0 deletions pkg/files/images/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func TestConvertImage(t *testing.T) {
},
},
}

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
Expand Down
9 changes: 6 additions & 3 deletions templates/partials/form.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
<div class="col-sm">
<label for="input-format" class="form-label">Formats to convert</label>
<select id="input-format" class="form-select" name="input_format">
<option selected>...</option>
{{ block "format-elements" . }}
{{ range $element := .Formats }}
<option value="{{ $element.Name }}">{{ $element.Name }}</option>
{{ range $family, $formats := . }}
<optgroup label="{{ $family }}">
{{ range $element := $formats }}
<option value="{{ $element }}">{{ $element }}</option>
{{ end }}
</optgroup>
{{ end }}
{{ end}}
</select>
Expand Down

0 comments on commit d76872c

Please sign in to comment.