86 lines
2.5 KiB
Go
86 lines
2.5 KiB
Go
package files
|
|
|
|
import (
|
|
"fmt"
|
|
"gis/app"
|
|
"gis/server/httputil"
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/minio/minio-go/v7"
|
|
)
|
|
|
|
func uploadFileRoute(application *app.App) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
if err := r.ParseMultipartForm(64 << 20); err != nil {
|
|
httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "request too large or not multipart"})
|
|
return
|
|
}
|
|
|
|
rawFileType := r.FormValue("file_type")
|
|
if rawFileType == "" {
|
|
httputil.WriteJSON(w, http.StatusUnprocessableEntity, map[string]string{"error": "file_type is required"})
|
|
return
|
|
}
|
|
ft := FileType(rawFileType)
|
|
if ft != FileTypeVectorWithTable && ft != FileTypeVector && ft != FileTypeRaster {
|
|
httputil.WriteJSON(w, http.StatusUnprocessableEntity, map[string]string{"error": "invalid file_type"})
|
|
return
|
|
}
|
|
|
|
f, header, err := r.FormFile("file")
|
|
if err != nil {
|
|
httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "file is required"})
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
ext := strings.ToLower(filepath.Ext(header.Filename))
|
|
if ext == "" {
|
|
httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "unsupported file format"})
|
|
return
|
|
}
|
|
if _, ok := allowedExtensions[ext]; !ok {
|
|
httputil.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "unsupported file format"})
|
|
return
|
|
}
|
|
|
|
storageKey := fmt.Sprintf("%d_%s", time.Now().UnixNano(), header.Filename)
|
|
|
|
_, err = application.S3.PutObject(
|
|
r.Context(),
|
|
application.Cfg.S3Bucket,
|
|
storageKey,
|
|
f,
|
|
header.Size,
|
|
minio.PutObjectOptions{ContentType: header.Header.Get("Content-Type")},
|
|
)
|
|
if err != nil {
|
|
httputil.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to store file"})
|
|
return
|
|
}
|
|
|
|
var gf GeoFile
|
|
err = application.Db.QueryRow(r.Context(),
|
|
`INSERT INTO files (filename, storage_key, file_type)
|
|
VALUES ($1, $2, $3)
|
|
RETURNING id, filename, file_type, validation_status,
|
|
validation_error, kato_column, crs, feature_count,
|
|
uploaded_at, updated_at`,
|
|
header.Filename, storageKey, ft,
|
|
).Scan(
|
|
&gf.ID, &gf.Filename, &gf.FileType, &gf.ValidationStatus,
|
|
&gf.ValidationError, &gf.KatoColumn, &gf.CRS, &gf.FeatureCount,
|
|
&gf.UploadedAt, &gf.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
httputil.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to save file record"})
|
|
return
|
|
}
|
|
|
|
httputil.WriteJSON(w, http.StatusAccepted, gf)
|
|
}
|
|
}
|