перенес создание протокола в Go Excelize
This commit is contained in:
107
server/protocol.go
Normal file
107
server/protocol.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"github.com/google/uuid"
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
type CreateProtocolRequest struct {
|
||||
TemplateID string `json:"template_id"`
|
||||
FileID string `json:"file_id"`
|
||||
CellsToUpdate map[string]any `json:"cells_to_update"`
|
||||
PrintArea string `json:"print_area"`
|
||||
}
|
||||
|
||||
func protocolHandler(backendURL string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse request body
|
||||
var req CreateProtocolRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch file binary from Python backend
|
||||
fileURL := fmt.Sprintf("%s/files/%s/content", backendURL, req.FileID)
|
||||
resp, err := http.Get(fileURL)
|
||||
if err != nil {
|
||||
http.Error(w, "failed to fetch file: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
http.Error(w, fmt.Sprintf("backend returned %d when fetching file", resp.StatusCode), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fileBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "failed to read file content: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Open xlsx with excelize
|
||||
f, err := excelize.OpenReader(bytes.NewReader(fileBytes))
|
||||
if err != nil {
|
||||
http.Error(w, "failed to open xlsx: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Get the first sheet
|
||||
sheetName := f.GetSheetName(0)
|
||||
if sheetName == "" {
|
||||
http.Error(w, "no sheets found in xlsx", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Fill cells
|
||||
for cellAddr, value := range req.CellsToUpdate {
|
||||
if err := setCellValue(f, sheetName, cellAddr, value); err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to set cell %s: %v", cellAddr, err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Write result to buffer
|
||||
var buf bytes.Buffer
|
||||
if err := f.Write(&buf); err != nil {
|
||||
http.Error(w, "failed to write xlsx: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
protocolID := uuid.New().String()
|
||||
|
||||
w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="protocol_%s.xlsx"`, protocolID))
|
||||
w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
|
||||
w.Write(buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func setCellValue(f *excelize.File, sheet, cell string, value any) error {
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
// JSON numbers are float64; check if it's actually an integer
|
||||
if v == float64(int64(v)) {
|
||||
return f.SetCellInt(sheet, cell, int64(v))
|
||||
}
|
||||
return f.SetCellFloat(sheet, cell, v, -1, 64)
|
||||
case string:
|
||||
return f.SetCellStr(sheet, cell, v)
|
||||
case bool:
|
||||
return f.SetCellBool(sheet, cell, v)
|
||||
case nil:
|
||||
return f.SetCellStr(sheet, cell, "")
|
||||
default:
|
||||
return f.SetCellStr(sheet, cell, fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user