推进活动系统最小成品闭环与游客体验
This commit is contained in:
132
backend/internal/httpapi/handlers/admin_asset_handler.go
Normal file
132
backend/internal/httpapi/handlers/admin_asset_handler.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"cmr-backend/internal/apperr"
|
||||
"cmr-backend/internal/httpx"
|
||||
"cmr-backend/internal/service"
|
||||
)
|
||||
|
||||
type AdminAssetHandler struct {
|
||||
service *service.AdminAssetService
|
||||
}
|
||||
|
||||
func NewAdminAssetHandler(service *service.AdminAssetService) *AdminAssetHandler {
|
||||
return &AdminAssetHandler{service: service}
|
||||
}
|
||||
|
||||
func (h *AdminAssetHandler) ListAssets(w http.ResponseWriter, r *http.Request) {
|
||||
result, err := h.service.ListManagedAssets(r.Context(), parseAdminLimit(r))
|
||||
if err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
|
||||
}
|
||||
|
||||
func (h *AdminAssetHandler) GetAsset(w http.ResponseWriter, r *http.Request) {
|
||||
result, err := h.service.GetManagedAsset(r.Context(), r.PathValue("assetPublicID"))
|
||||
if err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
|
||||
}
|
||||
|
||||
func (h *AdminAssetHandler) RegisterLink(w http.ResponseWriter, r *http.Request) {
|
||||
var req service.RegisterLinkAssetInput
|
||||
if err := httpx.DecodeJSON(r, &req); err != nil {
|
||||
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body: "+err.Error()))
|
||||
return
|
||||
}
|
||||
result, err := h.service.RegisterExternalLink(r.Context(), req)
|
||||
if err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusCreated, map[string]any{"data": result})
|
||||
}
|
||||
|
||||
func (h *AdminAssetHandler) UploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseMultipartForm(64 << 20); err != nil {
|
||||
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_multipart", "invalid multipart form: "+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "file_required", "multipart file field 'file' is required"))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "cmr-upload-*"+header.Filename)
|
||||
if err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
tmpPath := tmpFile.Name()
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
hash := sha256.New()
|
||||
written, err := io.Copy(io.MultiWriter(tmpFile, hash), file)
|
||||
if err != nil {
|
||||
tmpFile.Close()
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
input := service.UploadAssetFileInput{
|
||||
AssetType: r.FormValue("assetType"),
|
||||
AssetCode: r.FormValue("assetCode"),
|
||||
Version: r.FormValue("version"),
|
||||
Title: stringPtrOrNil(r.FormValue("title")),
|
||||
ObjectDir: stringPtrOrNil(r.FormValue("objectDir")),
|
||||
FileName: header.Filename,
|
||||
ContentType: header.Header.Get("Content-Type"),
|
||||
FileSize: written,
|
||||
Checksum: hex.EncodeToString(hash.Sum(nil)),
|
||||
TempPath: tmpPath,
|
||||
Status: r.FormValue("status"),
|
||||
Metadata: parseMetadataJSON(r.FormValue("metadataJson")),
|
||||
}
|
||||
|
||||
result, err := h.service.UploadAssetFile(r.Context(), input)
|
||||
if err != nil {
|
||||
httpx.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusCreated, map[string]any{
|
||||
"data": result,
|
||||
"meta": map[string]any{
|
||||
"uploadedBytes": written,
|
||||
"checksumSha256": input.Checksum,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func stringPtrOrNil(value string) *string {
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
return &value
|
||||
}
|
||||
|
||||
func parseMetadataJSON(raw string) map[string]any {
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
var payload map[string]any
|
||||
_ = json.Unmarshal([]byte(raw), &payload)
|
||||
return payload
|
||||
}
|
||||
Reference in New Issue
Block a user