upload files

This commit is contained in:
Niko Abeler 2023-07-08 12:03:10 +02:00
parent 9301790408
commit bcf8ba4d9b
7 changed files with 109 additions and 25 deletions

View File

@ -3,6 +3,7 @@ package main
import (
"bytes"
"io"
"io/ioutil"
"math/rand"
"mime/multipart"
"net/http/httptest"
@ -44,6 +45,7 @@ func TestEditorFormPost(t *testing.T) {
owlApp := App(db)
app := owlApp.FiberApp
repo := infra.NewEntryRepository(db, owlApp.Registry)
binRepo := infra.NewBinaryFileRepo(db)
fileDir, _ := os.Getwd()
fileName := "../../test/fixtures/test.png"
@ -51,11 +53,13 @@ func TestEditorFormPost(t *testing.T) {
file, err := os.Open(filePath)
require.NoError(t, err)
fileBytes, err := ioutil.ReadFile(filePath)
require.NoError(t, err)
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("ImagePath", filepath.Base(file.Name()))
part, _ := writer.CreateFormFile("ImageId", filepath.Base(file.Name()))
io.Copy(part, file)
part, _ = writer.CreateFormField("Content")
io.WriteString(part, "test content")
@ -72,6 +76,11 @@ func TestEditorFormPost(t *testing.T) {
entry, err := repo.FindById(id)
require.NoError(t, err)
require.Equal(t, "test content", entry.MetaData().(*model.ImageEntryMetaData).Content)
// require.Equal(t, "test.png", entry.MetaData().(*model.ImageEntryMetaData).ImagePath)
imageId := entry.MetaData().(*model.ImageEntryMetaData).ImageId
require.NotZero(t, imageId)
bin, err := binRepo.FindById(imageId)
require.NoError(t, err)
require.Equal(t, bin.Name, "test.png")
require.Equal(t, fileBytes, bin.Data)
}

View File

@ -1,6 +1,7 @@
package infra
import (
"owl-blogs/app/repository"
"owl-blogs/domain/model"
"github.com/google/uuid"
@ -17,7 +18,7 @@ type DefaultBinaryFileRepo struct {
db *sqlx.DB
}
func NewBinaryFileRepo(db Database) *DefaultBinaryFileRepo {
func NewBinaryFileRepo(db Database) repository.BinaryRepository {
sqlxdb := db.Get()
// Create table if not exists

View File

@ -23,7 +23,7 @@ func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegist
rssHandler := NewRSSHandler(entryService)
loginHandler := NewLoginHandler(entryService)
editorListHandler := NewEditorListHandler(typeRegistry)
editorHandler := NewEditorHandler(entryService, typeRegistry)
editorHandler := NewEditorHandler(entryService, typeRegistry, binService)
// app.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir()))
app.Get("/", indexHandler.Handle)

View File

@ -3,6 +3,7 @@ package editor
import (
"fmt"
"mime/multipart"
"owl-blogs/app"
"owl-blogs/domain/model"
"reflect"
"strings"
@ -21,7 +22,8 @@ type HttpFormData interface {
}
type EditorEntryForm struct {
entry model.Entry
entry model.Entry
binSvc *app.BinaryService
}
type EntryFormFieldParams struct {
@ -34,9 +36,10 @@ type EntryFormField struct {
Params EntryFormFieldParams
}
func NewEntryForm(entry model.Entry) *EditorEntryForm {
func NewEntryForm(entry model.Entry, binaryService *app.BinaryService) *EditorEntryForm {
return &EditorEntryForm{
entry: entry,
entry: entry,
binSvc: binaryService,
}
}
@ -103,7 +106,7 @@ func (s *EditorEntryForm) HtmlForm() (string, error) {
return "", err
}
html := "<form method=\"POST\">\n"
html := "<form method=\"POST\" enctype=\"multipart/form-data\">\n"
for _, field := range fields {
html += field.Html()
}
@ -126,13 +129,42 @@ func (s *EditorEntryForm) Parse(ctx HttpFormData) (model.Entry, error) {
if err != nil {
return nil, err
}
for field := range fields {
fieldName := fields[field].Name
fieldValue := ctx.FormValue(fieldName)
metaField := metaVal.Elem().FieldByName(fieldName)
if metaField.IsValid() {
metaField.SetString(fieldValue)
for _, field := range fields {
fieldName := field.Name
if field.Params.InputType == "file" {
file, err := ctx.FormFile(fieldName)
if err != nil {
return nil, err
}
fileData, err := file.Open()
if err != nil {
return nil, err
}
defer fileData.Close()
fileBytes := make([]byte, file.Size)
_, err = fileData.Read(fileBytes)
if err != nil {
return nil, err
}
binaryFile, err := s.binSvc.Create(file.Filename, fileBytes)
if err != nil {
return nil, err
}
metaField := metaVal.Elem().FieldByName(fieldName)
if metaField.IsValid() {
metaField.SetString(binaryFile.Id)
}
} else {
formValue := ctx.FormValue(fieldName)
metaField := metaVal.Elem().FieldByName(fieldName)
if metaField.IsValid() {
metaField.SetString(formValue)
}
}
}
return s.entry, nil

View File

@ -1,9 +1,17 @@
package editor_test
import (
"bytes"
"io"
"mime/multipart"
"os"
"owl-blogs/app"
"owl-blogs/domain/model"
"owl-blogs/infra"
"owl-blogs/test"
"owl-blogs/web/editor"
"path"
"path/filepath"
"reflect"
"testing"
"time"
@ -17,10 +25,41 @@ type MockEntryMetaData struct {
}
type MockFormData struct {
fileHeader *multipart.FileHeader
}
func NewMockFormData() *MockFormData {
fileDir, _ := os.Getwd()
fileName := "../../test/fixtures/test.png"
filePath := path.Join(fileDir, fileName)
file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("ImagePath", filepath.Base(file.Name()))
if err != nil {
panic(err)
}
io.Copy(part, file)
writer.Close()
multipartForm := multipart.NewReader(body, writer.Boundary())
formData, err := multipartForm.ReadForm(0)
if err != nil {
panic(err)
}
fileHeader := formData.File["ImagePath"][0]
return &MockFormData{fileHeader: fileHeader}
}
func (f *MockFormData) FormFile(key string) (*multipart.FileHeader, error) {
return nil, nil
return f.fileHeader, nil
}
func (f *MockFormData) FormValue(key string, defaultValue ...string) string {
@ -75,7 +114,7 @@ func TestStructToFields(t *testing.T) {
}
func TestEditorEntryForm_HtmlForm(t *testing.T) {
form := editor.NewEntryForm(&MockEntry{})
form := editor.NewEntryForm(&MockEntry{}, nil)
html, err := form.HtmlForm()
require.NoError(t, err)
require.Contains(t, html, "<form")
@ -87,15 +126,17 @@ func TestEditorEntryForm_HtmlForm(t *testing.T) {
}
func TestFormParseNil(t *testing.T) {
form := editor.NewEntryForm(&MockEntry{})
form := editor.NewEntryForm(&MockEntry{}, nil)
_, err := form.Parse(nil)
require.Error(t, err)
}
func TestFormParse(t *testing.T) {
form := editor.NewEntryForm(&MockEntry{})
entry, err := form.Parse(&MockFormData{})
binRepo := infra.NewBinaryFileRepo(test.NewMockDb())
binService := app.NewBinaryFileService(binRepo)
form := editor.NewEntryForm(&MockEntry{}, binService)
entry, err := form.Parse(NewMockFormData())
require.NoError(t, err)
require.Equal(t, "Image", entry.MetaData().(*MockEntryMetaData).Image)
require.NotZero(t, entry.MetaData().(*MockEntryMetaData).Image)
require.Equal(t, "Content", entry.MetaData().(*MockEntryMetaData).Content)
}

View File

@ -11,11 +11,12 @@ import (
type EditorHandler struct {
entrySvc *app.EntryService
binSvc *app.BinaryService
registry *app.EntryTypeRegistry
}
func NewEditorHandler(entryService *app.EntryService, registry *app.EntryTypeRegistry) *EditorHandler {
return &EditorHandler{entrySvc: entryService, registry: registry}
func NewEditorHandler(entryService *app.EntryService, registry *app.EntryTypeRegistry, binService *app.BinaryService) *EditorHandler {
return &EditorHandler{entrySvc: entryService, registry: registry, binSvc: binService}
}
func (h *EditorHandler) paramToEntry(c *fiber.Ctx) (model.Entry, error) {
@ -35,7 +36,7 @@ func (h *EditorHandler) HandleGet(c *fiber.Ctx) error {
return err
}
form := editor.NewEntryForm(entryType)
form := editor.NewEntryForm(entryType, h.binSvc)
htmlForm, err := form.HtmlForm()
if err != nil {
return err
@ -51,7 +52,7 @@ func (h *EditorHandler) HandlePost(c *fiber.Ctx) error {
return err
}
form := editor.NewEntryForm(entryType)
form := editor.NewEntryForm(entryType, h.binSvc)
// get form data
entry, err := form.Parse(c)
if err != nil {

View File

@ -2,7 +2,7 @@
{{define "main"}}
{{.MetaData.ImagePath}}
{{.MetaData.ImageId}}
<p>
{{.Content}}