108 lines
2.9 KiB
Go
108 lines
2.9 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jmoiron/sqlx"
|
|
"workorders/internal/config"
|
|
"workorders/internal/model"
|
|
)
|
|
|
|
type AttachmentHandler struct {
|
|
db *sqlx.DB
|
|
cfg *config.Config
|
|
}
|
|
|
|
func NewAttachmentHandler(db *sqlx.DB, cfg *config.Config) *AttachmentHandler {
|
|
return &AttachmentHandler{db: db, cfg: cfg}
|
|
}
|
|
|
|
func (h *AttachmentHandler) List(w http.ResponseWriter, r *http.Request) {
|
|
woID, err := intParam(r, "id")
|
|
if err != nil {
|
|
respondError(w, http.StatusBadRequest, "invalid id")
|
|
return
|
|
}
|
|
var atts []model.Attachment
|
|
if err := h.db.Select(&atts, `SELECT * FROM wo_attachments WHERE wo_id=@p1 ORDER BY uploaded_at`, woID); err != nil {
|
|
respondError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
for i := range atts {
|
|
atts[i].URL = "/uploads/" + atts[i].FilePath
|
|
}
|
|
respond(w, http.StatusOK, atts)
|
|
}
|
|
|
|
func (h *AttachmentHandler) Upload(w http.ResponseWriter, r *http.Request) {
|
|
woID, err := intParam(r, "id")
|
|
if err != nil {
|
|
respondError(w, http.StatusBadRequest, "invalid id")
|
|
return
|
|
}
|
|
user := userFromCtx(r)
|
|
|
|
if err := r.ParseMultipartForm(32 << 20); err != nil {
|
|
respondError(w, http.StatusBadRequest, "parse form failed")
|
|
return
|
|
}
|
|
file, header, err := r.FormFile("file")
|
|
if err != nil {
|
|
respondError(w, http.StatusBadRequest, "missing file")
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
ext := filepath.Ext(header.Filename)
|
|
fname := uuid.New().String() + ext
|
|
relPath := fmt.Sprintf("%d/%s", woID, fname)
|
|
absPath := filepath.Join(h.cfg.UploadPath, relPath)
|
|
|
|
if err := os.MkdirAll(filepath.Dir(absPath), 0755); err != nil {
|
|
respondError(w, http.StatusInternalServerError, "storage error")
|
|
return
|
|
}
|
|
dst, err := os.Create(absPath)
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, "storage error")
|
|
return
|
|
}
|
|
defer dst.Close()
|
|
size, _ := io.Copy(dst, file)
|
|
|
|
var aid int
|
|
err = h.db.QueryRow(`
|
|
INSERT INTO wo_attachments (wo_id,file_name,file_path,file_type,file_size,caption,phase,uploaded_by)
|
|
OUTPUT INSERTED.id VALUES (@p1,@p2,@p3,@p4,@p5,@p6,@p7,@p8)`,
|
|
woID, header.Filename, relPath, header.Header.Get("Content-Type"),
|
|
size, r.FormValue("caption"), r.FormValue("phase"), user.Email,
|
|
).Scan(&aid)
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
respond(w, http.StatusCreated, map[string]any{
|
|
"id": aid,
|
|
"url": "/uploads/" + relPath,
|
|
})
|
|
}
|
|
|
|
func (h *AttachmentHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
|
aid, err := intParam(r, "aid")
|
|
if err != nil {
|
|
respondError(w, http.StatusBadRequest, "invalid aid")
|
|
return
|
|
}
|
|
var att model.Attachment
|
|
if err := h.db.Get(&att, `SELECT * FROM wo_attachments WHERE id=@p1`, aid); err == nil {
|
|
os.Remove(filepath.Join(h.cfg.UploadPath, att.FilePath))
|
|
}
|
|
h.db.Exec(`DELETE FROM wo_attachments WHERE id=@p1`, aid)
|
|
respond(w, http.StatusOK, map[string]any{"deleted": aid})
|
|
}
|