This repository has been archived on 2023-11-13. You can view files and clone it, but cannot push or open issues or pull requests.
imagini/internal/api/media_items.go
2021-01-19 21:18:08 -05:00

133 lines
3.8 KiB
Go

package api
import (
"io"
"os"
"fmt"
"strings"
"net/http"
"encoding/json"
log "github.com/sirupsen/logrus"
"github.com/dsoprea/go-exif/v3"
"reichard.io/imagini/internal/models"
)
func (api *API) mediaItemsHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
// CREATE
api.createMediaItem(w, r)
} else if r.Method == http.MethodPut {
// UPDATE / REPLACE
} else if r.Method == http.MethodPatch {
// UPDATE / MODIFY
} else if r.Method == http.MethodDelete {
// DELETE
} else if r.Method == http.MethodGet {
// GET
} else {
errorJSON(w, "Method is not supported.", http.StatusMethodNotAllowed)
return
}
}
func (api *API) createMediaItem(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(64 << 20)
// Parse metadata
metadata := r.FormValue("metadata")
var mediaItem models.MediaItem
err := json.Unmarshal([]byte(metadata), &mediaItem)
if err != nil {
log.Warn("[api] createMediaItem - Invalid metadata: ", err)
errorJSON(w, "Metadata invalid.", http.StatusBadRequest)
return
}
// TODO: Verify mediaItem contains appropriate values
// fmt.Printf("Media Item: %+v\n", mediaItem)
// Open form file
formFile, multipartFileHeader, err := r.FormFile("file")
if err != nil {
errorJSON(w, "Upload failed.", http.StatusInternalServerError)
return
}
defer formFile.Close()
// File header placeholder
fileHeader := make([]byte, 512)
// Copy headers into the buffer
if _, err := formFile.Read(fileHeader); err != nil {
errorJSON(w, "Upload failed.", http.StatusInternalServerError)
return
}
// Reset position
if _, err := formFile.Seek(0, 0); err != nil {
errorJSON(w, "Upload failed.", http.StatusInternalServerError)
return
}
// Determine media type
var mediaType string
contentType := http.DetectContentType(fileHeader)
if strings.HasPrefix(contentType, "image/") {
mediaType = "Image"
} else if strings.HasPrefix(contentType, "video/") {
mediaType = "Video"
} else {
errorJSON(w, "Invalid filetype.", http.StatusUnsupportedMediaType)
return
}
_ = mediaType
_ = multipartFileHeader
// Print details
// Filename: multipartFileHeader.Filename
// Size: multipartFileHeader.Size
// ContentType: http.DetectContentType(fileHeader)
// Open file to store
filePath := "./test.png" // TODO: Change dynamic
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
log.Warn("[api] createMediaItem - Unable to open file: ", filePath)
errorJSON(w, "Upload failed.", http.StatusInternalServerError)
return
}
defer f.Close()
// Copy data to file
_, err = io.Copy(f, formFile)
if err != nil {
errorJSON(w, "Upload failed.", http.StatusInternalServerError)
return
}
// Gather EXIF Data
mediaItem = deriveEXIFData(filePath, mediaItem)
// TODO: Add resource location in response
successJSON(w, "Upload succeeded.", http.StatusCreated)
}
func deriveEXIFData(filePath string, mediaItem models.MediaItem) models.MediaItem {
rawExif, err := exif.SearchFileAndExtractExif(filePath)
entries, _, err := exif.GetFlatExifData(rawExif, nil)
_ = err
// parsedJSON, err := json.MarshalIndent(entries, "", " ")
// fmt.Printf("EXIF String: %+v\n", string(parsedJSON))
for _, entry := range entries {
fmt.Printf("IFD-PATH=[%s] ID=(0x%04x) NAME=[%s] COUNT=(%d) TYPE=[%s] VALUE=[%s]\n", entry.IfdPath, entry.TagId, entry.TagName, entry.UnitCount, entry.TagTypeName, entry.Formatted)
}
return mediaItem
}