package image import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "os" "path/filepath" ) // PddUploadResult 用于解析 PDD 上传返回的 result JSON type PddUploadResult struct { URL string `json:"url"` } // UploadResponse 用于解析上传接口完整响应 type UploadResponse struct { Data struct { PddUpload struct { Result string `json:"result"` Success bool `json:"success"` } `json:"pddUpload"` } `json:"data"` Success bool `json:"success"` Message string `json:"message"` } // DownloadFile 下载图片到临时文件 func DownloadFile(url string) (string, error) { resp, err := http.Get(url) if err != nil { return "", fmt.Errorf("下载文件失败: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("下载失败, 状态码: %d", resp.StatusCode) } tmpFile, err := os.CreateTemp("", "book_image_*.png") if err != nil { return "", fmt.Errorf("创建临时文件失败: %w", err) } defer tmpFile.Close() _, err = io.Copy(tmpFile, resp.Body) if err != nil { return "", fmt.Errorf("写入临时文件失败: %w", err) } return tmpFile.Name(), nil } // UploadBookImage 上传图片并返回 PDD URL func UploadBookImage(filePath, isbn, isKW, goodsName, autoUpload string) (string, error) { file, err := os.Open(filePath) if err != nil { return "", fmt.Errorf("打开文件失败: %w", err) } defer file.Close() var body bytes.Buffer writer := multipart.NewWriter(&body) part, err := writer.CreateFormFile("filepath", filepath.Base(file.Name())) if err != nil { return "", fmt.Errorf("创建文件字段失败: %w", err) } if _, err := io.Copy(part, file); err != nil { return "", fmt.Errorf("复制文件内容失败: %w", err) } fields := map[string]string{ "isbn": isbn, "isKW": isKW, "goodsName": goodsName, "autoUpload": autoUpload, } for k, v := range fields { if err := writer.WriteField(k, v); err != nil { return "", fmt.Errorf("写入字段 %s 失败: %w", k, err) } } if err := writer.Close(); err != nil { return "", fmt.Errorf("关闭 writer 失败: %w", err) } req, err := http.NewRequest("POST", "http://103.236.81.185:9000/processImage", &body) if err != nil { return "", fmt.Errorf("创建请求失败: %w", err) } req.Header.Set("Content-Type", writer.FormDataContentType()) client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("发送请求失败: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("读取响应失败: %w", err) } var uploadResp UploadResponse if err := json.Unmarshal(respBody, &uploadResp); err != nil { return "", fmt.Errorf("解析响应失败: %w", err) } if !uploadResp.Data.PddUpload.Success { return "", fmt.Errorf("上传失败: %s", uploadResp.Message) } // 解析 result 字段中的 JSON var result PddUploadResult if err := json.Unmarshal([]byte(uploadResp.Data.PddUpload.Result), &result); err != nil { return "", fmt.Errorf("解析 PDD result 失败: %w", err) } return result.URL, nil } // DownloadAndUploadBookImage 下载图片并上传,返回 PDD URL func DownloadAndUploadBookImage(imageURL, isbn, isKW, goodsName, autoUpload string) (string, error) { tmpFile, err := DownloadFile(imageURL) if err != nil { return "", err } defer os.Remove(tmpFile) // 使用完删除临时文件 return UploadBookImage(tmpFile, isbn, isKW, goodsName, autoUpload) }