114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
|
|
package client
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"bytes"
|
|||
|
|
"encoding/json"
|
|||
|
|
"fmt"
|
|||
|
|
"io"
|
|||
|
|
"log"
|
|||
|
|
"net/http"
|
|||
|
|
"qd-sc/internal/config"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// OCRClient OCR服务客户端
|
|||
|
|
type OCRClient struct {
|
|||
|
|
baseURL string
|
|||
|
|
httpClient *http.Client
|
|||
|
|
logLevel string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// OCRResponse OCR服务响应结构
|
|||
|
|
type OCRResponse struct {
|
|||
|
|
Code int `json:"code"`
|
|||
|
|
Data string `json:"data"`
|
|||
|
|
CostTimeMs float64 `json:"cost_time_ms"`
|
|||
|
|
Msg string `json:"msg,omitempty"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewOCRClient 创建OCR客户端
|
|||
|
|
func NewOCRClient(cfg *config.Config) *OCRClient {
|
|||
|
|
return &OCRClient{
|
|||
|
|
baseURL: cfg.OCR.BaseURL,
|
|||
|
|
httpClient: NewHTTPClient(HTTPClientConfig{Timeout: cfg.OCR.Timeout, MaxIdleConns: 100, MaxIdleConnsPerHost: 50, MaxConnsPerHost: 0}),
|
|||
|
|
logLevel: cfg.Logging.Level,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ParseURL 通过URL解析远程文件内容
|
|||
|
|
// 支持图片、PDF、Excel、PPT等格式
|
|||
|
|
func (c *OCRClient) ParseURL(fileURL string) (string, error) {
|
|||
|
|
// 构建请求体
|
|||
|
|
reqBody := map[string]string{
|
|||
|
|
"url": fileURL,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reqData, err := json.Marshal(reqBody)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("序列化请求失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 打印文件解析请求体
|
|||
|
|
log.Printf("OCR文件解析请求: URL=%s, 请求体=%s", c.baseURL+"/ocr/url", string(reqData))
|
|||
|
|
|
|||
|
|
// 创建HTTP请求
|
|||
|
|
httpReq, err := http.NewRequest("POST", c.baseURL+"/ocr/url", bytes.NewReader(reqData))
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("创建HTTP请求失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
httpReq.Header.Set("Content-Type", "application/json")
|
|||
|
|
|
|||
|
|
// 发送请求
|
|||
|
|
resp, err := c.httpClient.Do(httpReq)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("HTTP请求失败: %w", err)
|
|||
|
|
}
|
|||
|
|
defer resp.Body.Close()
|
|||
|
|
|
|||
|
|
// 读取响应
|
|||
|
|
respBody, err := io.ReadAll(resp.Body)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("读取响应失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 打印原始响应(仅在debug级别时显示完整响应,否则显示摘要)
|
|||
|
|
if c.logLevel == "debug" {
|
|||
|
|
log.Printf("OCR原始响应: %s", string(respBody))
|
|||
|
|
} else {
|
|||
|
|
// 非debug模式下显示响应摘要
|
|||
|
|
if len(respBody) > 200 {
|
|||
|
|
log.Printf("OCR响应摘要: %s... (共%d字节)", string(respBody[:200]), len(respBody))
|
|||
|
|
} else {
|
|||
|
|
log.Printf("OCR响应: %s", string(respBody))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析响应
|
|||
|
|
var ocrResp OCRResponse
|
|||
|
|
if err := json.Unmarshal(respBody, &ocrResp); err != nil {
|
|||
|
|
return "", fmt.Errorf("解析响应失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 打印解析结果
|
|||
|
|
log.Printf("OCR解析结果: Code=%d, CostTimeMs=%.2f, 数据长度=%d字节", ocrResp.Code, ocrResp.CostTimeMs, len(ocrResp.Data))
|
|||
|
|
if c.logLevel == "debug" && ocrResp.Data != "" {
|
|||
|
|
// debug模式下打印解析出的数据内容
|
|||
|
|
if len(ocrResp.Data) > 500 {
|
|||
|
|
log.Printf("OCR解析数据(前500字符): %s...", ocrResp.Data[:500])
|
|||
|
|
} else {
|
|||
|
|
log.Printf("OCR解析数据: %s", ocrResp.Data)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查业务状态码
|
|||
|
|
if ocrResp.Code != 200 {
|
|||
|
|
errMsg := ocrResp.Msg
|
|||
|
|
if errMsg == "" {
|
|||
|
|
errMsg = "OCR解析失败"
|
|||
|
|
}
|
|||
|
|
return "", fmt.Errorf("OCR服务返回错误: %s", errMsg)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ocrResp.Data, nil
|
|||
|
|
}
|