package clients import ( "bytes" "context" "encoding/json" "io" "mime/multipart" "net/http" "go.uber.org/zap" ) // PostScreenShotReq 申报截图上传参数 type PostScreenShotReq struct { Name string // 文件名 TaxNo string // 税号 Period string // 账期 } // 申报截图上传响应 type PostScreenshotResp struct { Path string `json:"path"` // 截图路径 } // FileClient 文件客户端 type FileClient struct { Client *http.Client // 客户端 Logger *zap.Logger // 日志 } // PostScreenShotBytes 上传文件 返回上传的 url 参数 bs 为文件内容 func (c FileClient) PostScreenShotBytes(ctx context.Context, bs []byte, p PostScreenShotReq) (string, error) { return c.PostScreenShot(ctx, bytes.NewReader(bs), p) } // PostScreenShot 上传截图 返回上传的 url func (c FileClient) PostScreenShot(ctx context.Context, r io.Reader, p PostScreenShotReq) (string, error) { var b bytes.Buffer mw, err := c.writeMultipart(&b, p, r) if err != nil { return "", err } const u = "https://file.listensoft.net/api/v1/uploadsbjt" req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, &b) if err != nil { return "", err } req.Header.Set("Content-Type", mw.FormDataContentType()) c.Logger.Debug("上传截图", zap.String("url", u), zap.String("name", p.Name)) resp, err := c.Client.Do(req) if err != nil { return "", err } defer resp.Body.Close() bs, err := io.ReadAll(resp.Body) if err != nil { return "", err } var response PostScreenshotResp err = json.Unmarshal(bs, &response) if err != nil { return "", err } path := response.Path c.Logger.Debug("上传截图成功", zap.String("name", p.Name), zap.String("path", path)) return path, nil } func (c FileClient) writeMultipart(w io.Writer, param PostScreenShotReq, r io.Reader) (*multipart.Writer, error) { mw := multipart.NewWriter(w) err := writeFileFromReader(mw, "file", param.Name, r) if err != nil { return nil, err } err = mw.WriteField("tax_no", param.TaxNo) if err != nil { return nil, err } err = mw.WriteField("period", param.Period) if err != nil { return nil, err } err = mw.WriteField("type", "etax") if err != nil { return nil, err } err = mw.Close() if err != nil { return nil, err } return mw, nil }