package cos import ( "bytes" "context" "encoding/base64" "encoding/json" "encoding/xml" "errors" "fmt" "hash/crc64" "io" "net/http" "os" "strconv" ) type CIService service type PicOperations struct { IsPicInfo int `json:"is_pic_info,omitempty"` Rules []PicOperationsRules `json:"rules,omitemtpy"` } type PicOperationsRules struct { Bucket string `json:"bucket,omitempty"` FileId string `json:"fileid"` Rule string `json:"rule"` } func EncodePicOperations(pic *PicOperations) string { if pic == nil { return "" } bs, err := json.Marshal(pic) if err != nil { return "" } return string(bs) } type ImageProcessResult struct { XMLName xml.Name `xml:"UploadResult"` OriginalInfo *PicOriginalInfo `xml:"OriginalInfo,omitempty"` ProcessResults *PicProcessObject `xml:"ProcessResults>Object,omitempty"` } type PicOriginalInfo struct { Key string `xml:"Key,omitempty"` Location string `xml:"Location,omitempty"` ImageInfo *PicImageInfo `xml:"ImageInfo,omitempty"` ETag string `xml:"ETag,omitempty"` } type PicImageInfo struct { Format string `xml:"Format,omitempty"` Width int `xml:"Width,omitempty"` Height int `xml:"Height,omitempty"` Quality int `xml:"Quality,omitempty"` Ave string `xml:"Ave,omitempty"` Orientation int `xml:"Orientation,omitempty"` } type PicProcessObject struct { Key string `xml:"Key,omitempty"` Location string `xml:"Location,omitempty"` Format string `xml:"Format,omitempty"` Width int `xml:"Width,omitempty"` Height int `xml:"Height,omitempty"` Size int `xml:"Size,omitempty"` Quality int `xml:"Quality,omitempty"` ETag string `xml:"ETag,omitempty"` WatermarkStatus int `xml:"WatermarkStatus,omitempty"` CodeStatus int `xml:"CodeStatus,omitempty"` QRcodeInfo []QRcodeInfo `xml:"QRcodeInfo,omitempty"` } type QRcodeInfo struct { CodeUrl string `xml:"CodeUrl,omitempty"` CodeLocation *CodeLocation `xml:"CodeLocation,omitempty"` } type CodeLocation struct { Point []string `xml:"Point,omitempty"` } type picOperationsHeader struct { PicOperations string `header:"Pic-Operations" xml:"-" url:"-"` } type ImageProcessOptions = PicOperations // 云上数据处理 https://cloud.tencent.com/document/product/460/18147 func (s *CIService) ImageProcess(ctx context.Context, name string, opt *ImageProcessOptions) (*ImageProcessResult, *Response, error) { header := &picOperationsHeader{ PicOperations: EncodePicOperations(opt), } var res ImageProcessResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: "/" + encodeURIComponent(name) + "?image_process", method: http.MethodPost, optHeader: header, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // ImageRecognitionOptions is the option of ImageAuditing type ImageRecognitionOptions struct { CIProcess string `url:"ci-process,omitempty"` DetectType string `url:"detect-type,omitempty"` DetectUrl string `url:"detect-url,omitempty"` Interval int `url:"interval,omitempty"` MaxFrames int `url:"max-frames,omitempty"` BizType string `url:"biz-type,omitempty"` } // ImageRecognitionResult is the result of ImageRecognition/ImageAuditing type ImageRecognitionResult struct { XMLName xml.Name `xml:"RecognitionResult"` Text string `xml:"Text,omitempty"` Label string `xml:"Label,omitempty"` Result int `xml:"Result,omitempty"` Score int `xml:"Score,omitempty"` SubLabel string `xml:"SubLabel,omitempty"` PornInfo *RecognitionInfo `xml:"PornInfo,omitempty"` TerroristInfo *RecognitionInfo `xml:"TerroristInfo,omitempty"` PoliticsInfo *RecognitionInfo `xml:"PoliticsInfo,omitempty"` AdsInfo *RecognitionInfo `xml:"AdsInfo,omitempty"` } // RecognitionInfo is the result of auditing scene type RecognitionInfo struct { Code int `xml:"Code,omitempty"` Msg string `xml:"Msg,omitempty"` HitFlag int `xml:"HitFlag,omitempty"` Score int `xml:"Score,omitempty"` Label string `xml:"Label,omitempty"` Count int `xml:"Count,omitempty"` SubLabel string `xml:"SubLabel,omitempty"` Keywords string `xml:"Keywords,omitempty"` OcrResults []OcrResult `xml:"OcrResults,omitempty"` ObjectResults []ObjectResult `xml:"ObjectResults,omitempty"` LibResults []LibResult `xml:"LibResults,omitempty"` } // 图片审核 https://cloud.tencent.com/document/product/460/37318 func (s *CIService) ImageRecognition(ctx context.Context, name string, DetectType string) (*ImageRecognitionResult, *Response, error) { opt := &ImageRecognitionOptions{ CIProcess: "sensitive-content-recognition", DetectType: DetectType, } var res ImageRecognitionResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: "/" + encodeURIComponent(name), method: http.MethodGet, optQuery: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // 图片审核 支持detect-url等全部参数 func (s *CIService) ImageAuditing(ctx context.Context, name string, opt *ImageRecognitionOptions) (*ImageRecognitionResult, *Response, error) { var res ImageRecognitionResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: "/" + encodeURIComponent(name), method: http.MethodGet, optQuery: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // PutVideoAuditingJobOptions is the option of PutVideoAuditingJob type PutVideoAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputObject string `xml:"Input>Object,omitempty"` InputUrl string `xml:"Input>Url,omitempty"` Conf *VideoAuditingJobConf `xml:"Conf"` } // VideoAuditingJobConf is the config of PutVideoAuditingJobOptions type VideoAuditingJobConf struct { DetectType string `xml:",omitempty"` Snapshot *PutVideoAuditingJobSnapshot `xml:",omitempty"` Callback string `xml:",omitempty"` CallbackVersion string `xml:",omitempty"` BizType string `xml:",omitempty"` DetectContent int `xml:",omitempty"` } // PutVideoAuditingJobSnapshot is the snapshot config of VideoAuditingJobConf type PutVideoAuditingJobSnapshot struct { Mode string `xml:",omitempty"` Count int `xml:",omitempty"` TimeInterval float32 `xml:",omitempty"` Start float32 `xml:",omitempty"` } // PutVideoAuditingJobResult is the result of PutVideoAuditingJob type PutVideoAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail struct { JobId string `xml:"JobId,omitempty"` State string `xml:"State,omitempty"` CreationTime string `xml:"CreationTime,omitempty"` Object string `xml:"Object,omitempty"` } `xml:"JobsDetail,omitempty"` } // 视频审核-创建任务 https://cloud.tencent.com/document/product/460/46427 func (s *CIService) PutVideoAuditingJob(ctx context.Context, opt *PutVideoAuditingJobOptions) (*PutVideoAuditingJobResult, *Response, error) { var res PutVideoAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/video/auditing", method: http.MethodPost, body: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // GetVideoAuditingJobResult is the result of GetVideoAuditingJob type GetVideoAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *AuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } // AuditingJobDetail is the detail of GetVideoAuditingJobResult type AuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` JobId string `xml:",omitempty"` State string `xml:",omitempty"` CreationTime string `xml:",omitempty"` Object string `xml:",omitempty"` Url string `xml:",omitempty"` SnapshotCount string `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` Snapshot []GetVideoAuditingJobSnapshot `xml:",omitempty"` AudioSection []AudioSectionResult `xml:",omitempty"` } // GetVideoAuditingJobSnapshot is the snapshot result of AuditingJobDetail type GetVideoAuditingJobSnapshot struct { Url string `xml:",omitempty"` Text string `xml:",omitempty"` SnapshotTime int `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } // AudioSectionResult is the audio section result of AuditingJobDetail/AudioAuditingJobDetail type AudioSectionResult struct { Url string `xml:",omitempty"` Text string `xml:",omitempty"` OffsetTime int `xml:",omitempty"` Duration int `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } // 视频审核-查询任务 https://cloud.tencent.com/document/product/460/46926 func (s *CIService) GetVideoAuditingJob(ctx context.Context, jobid string) (*GetVideoAuditingJobResult, *Response, error) { var res GetVideoAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/video/auditing/" + jobid, method: http.MethodGet, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // PutAudioAuditingJobOptions is the option of PutAudioAuditingJob type PutAudioAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputObject string `xml:"Input>Object,omitempty"` InputUrl string `xml:"Input>Url,omitempty"` Conf *AudioAuditingJobConf `xml:"Conf"` } // AudioAuditingJobConf is the config of PutAudioAuditingJobOptions type AudioAuditingJobConf struct { DetectType string `xml:",omitempty"` Callback string `xml:",omitempty"` CallbackVersion string `xml:",omitempty"` BizType string `xml:",omitempty"` } // PutAudioAuditingJobResult is the result of PutAudioAuditingJob type PutAudioAuditingJobResult PutVideoAuditingJobResult // 音频审核-创建任务 https://cloud.tencent.com/document/product/460/53395 func (s *CIService) PutAudioAuditingJob(ctx context.Context, opt *PutAudioAuditingJobOptions) (*PutAudioAuditingJobResult, *Response, error) { var res PutAudioAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/audio/auditing", method: http.MethodPost, body: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // GetAudioAuditingJobResult is the result of GetAudioAuditingJob type GetAudioAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *AudioAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } // AudioAuditingJobDetail is the detail of GetAudioAuditingJobResult type AudioAuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` JobId string `xml:",omitempty"` State string `xml:",omitempty"` CreationTime string `xml:",omitempty"` Object string `xml:",omitempty"` Url string `xml:",omitempty"` AudioText string `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` Section *AudioSectionResult `xml:",omitempty"` } // 音频审核-查询任务 https://cloud.tencent.com/document/product/460/53396 func (s *CIService) GetAudioAuditingJob(ctx context.Context, jobid string) (*GetAudioAuditingJobResult, *Response, error) { var res GetAudioAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/audio/auditing/" + jobid, method: http.MethodGet, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // PutTextAuditingJobOptions is the option of PutTextAuditingJob type PutTextAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputObject string `xml:"Input>Object,omitempty"` InputContent string `xml:"Input>Content,omitempty"` Conf *TextAuditingJobConf `xml:"Conf"` } // TextAuditingJobConf is the config of PutAudioAuditingJobOptions type TextAuditingJobConf struct { DetectType string `xml:",omitempty"` Callback string `xml:",omitempty"` CallbackVersion string `xml:",omitempty"` BizType string `xml:",omitempty"` } // PutTextAuditingJobResult is the result of PutTextAuditingJob type PutTextAuditingJobResult GetTextAuditingJobResult // 文本审核-创建任务 https://cloud.tencent.com/document/product/436/56289 func (s *CIService) PutTextAuditingJob(ctx context.Context, opt *PutTextAuditingJobOptions) (*PutTextAuditingJobResult, *Response, error) { var res PutTextAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/text/auditing", method: http.MethodPost, body: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // GetTextAuditingJobResult is the result of GetTextAuditingJob type GetTextAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *TextAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } // TextAuditingJobDetail is the detail of GetTextAuditingJobResult type TextAuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` JobId string `xml:",omitempty"` State string `xml:",omitempty"` CreationTime string `xml:",omitempty"` Object string `xml:",omitempty"` Url string `xml:",omitempty"` Content string `xml:",omitempty"` SectionCount int `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` IllegalInfo *RecognitionInfo `xml:",omitempty"` AbuseInfo *RecognitionInfo `xml:",omitempty"` Section []TextSectionResult `xml:",omitempty"` } // TextSectionResult is the section result of TextAuditingJobDetail type TextSectionResult struct { StartByte int `xml:",omitempty"` Label string `xml:",omitempty"` Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` IllegalInfo *RecognitionInfo `xml:",omitempty"` AbuseInfo *RecognitionInfo `xml:",omitempty"` } // 文本审核-查询任务 https://cloud.tencent.com/document/product/436/56288 func (s *CIService) GetTextAuditingJob(ctx context.Context, jobid string) (*GetTextAuditingJobResult, *Response, error) { var res GetTextAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/text/auditing/" + jobid, method: http.MethodGet, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // PutDocumentAuditingJobOptions is the option of PutDocumentAuditingJob type PutDocumentAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputUrl string `xml:"Input>Url,omitempty"` InputType string `xml:"Input>Type,omitempty"` Conf *DocumentAuditingJobConf `xml:"Conf"` } // DocumentAuditingJobConf is the config of PutDocumentAuditingJobOptions type DocumentAuditingJobConf struct { DetectType string `xml:",omitempty"` Callback string `xml:",omitempty"` BizType string `xml:",omitempty"` } // PutDocumentAuditingJobResult is the result of PutDocumentAuditingJob type PutDocumentAuditingJobResult PutVideoAuditingJobResult // 文档审核-创建任务 https://cloud.tencent.com/document/product/436/59381 func (s *CIService) PutDocumentAuditingJob(ctx context.Context, opt *PutDocumentAuditingJobOptions) (*PutDocumentAuditingJobResult, *Response, error) { var res PutDocumentAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/document/auditing", method: http.MethodPost, body: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // GetDocumentAuditingJobResult is the result of GetDocumentAuditingJob type GetDocumentAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *DocumentAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } // DocumentAuditingJobDetail is the detail of GetDocumentAuditingJobResult type DocumentAuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` JobId string `xml:",omitempty"` State string `xml:",omitempty"` CreationTime string `xml:",omitempty"` Object string `xml:",omitempty"` Url string `xml:",omitempty"` PageCount int `xml:",omitempty"` Label string `xml:",omitempty"` Suggestion int `xml:",omitempty"` Labels *DocumentResultInfo `xml:",omitempty"` PageSegment *DocumentPageSegmentInfo `xml:",omitempty"` } // DocumentResultInfo type DocumentResultInfo struct { PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } // DocumentPageSegmentInfo type DocumentPageSegmentInfo struct { Results []DocumentPageSegmentResultResult `xml:",omitempty"` } // DocumentPageSegmentResultResult type DocumentPageSegmentResultResult struct { Url string `xml:",omitempty"` Text string `xml:",omitempty"` PageNumber int `xml:",omitempty"` SheetNumber int `xml:",omitempty"` Label string `xml:",omitempty"` Suggestion int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } // OcrResult type OcrResult struct { Text string `xml:"Text"` Keywords []string `xml:"Keywords"` Location *Location `xml:"Location,omitempty"` } // ObjectResult type ObjectResult struct { Name string `xml:"Name"` Location *Location `xml:"Location,omitempty"` } // LibResult type LibResult struct { ImageId string `xml:"ImageId"` Score uint32 `xml:"Score"` } // Location type Location struct { X float64 `xml:"X,omitempty"` // 左上角横坐标 Y float64 `xml:"Y,omitempty"` // 左上角纵坐标 Width float64 `xml:"Width,omitempty"` // 宽度 Height float64 `xml:"Height,omitempty"` // 高度 Rotate float64 `xml:"Rotate,omitempty"` // 检测框的旋转角度 } // 文档审核-查询任务 https://cloud.tencent.com/document/product/436/59382 func (s *CIService) GetDocumentAuditingJob(ctx context.Context, jobid string) (*GetDocumentAuditingJobResult, *Response, error) { var res GetDocumentAuditingJobResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/document/auditing/" + jobid, method: http.MethodGet, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // 图片持久化处理-上传时处理 https://cloud.tencent.com/document/product/460/18147 // 盲水印-上传时添加 https://cloud.tencent.com/document/product/460/19017 // 二维码识别-上传时识别 https://cloud.tencent.com/document/product/460/37513 func (s *CIService) Put(ctx context.Context, name string, r io.Reader, uopt *ObjectPutOptions) (*ImageProcessResult, *Response, error) { if r == nil { return nil, nil, fmt.Errorf("reader is nil") } if err := CheckReaderLen(r); err != nil { return nil, nil, err } opt := CloneObjectPutOptions(uopt) totalBytes, err := GetReaderLen(r) if err != nil && opt != nil && opt.Listener != nil { if opt.ContentLength == 0 { return nil, nil, err } totalBytes = opt.ContentLength } if err == nil { // 与 go http 保持一致, 非bytes.Buffer/bytes.Reader/strings.Reader由用户指定ContentLength, 或使用 Chunk 上传 if opt != nil && opt.ContentLength == 0 && IsLenReader(r) { opt.ContentLength = totalBytes } } reader := TeeReader(r, nil, totalBytes, nil) if s.client.Conf.EnableCRC { reader.writer = crc64.New(crc64.MakeTable(crc64.ECMA)) } if opt != nil && opt.Listener != nil { reader.listener = opt.Listener } var res ImageProcessResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: "/" + encodeURIComponent(name), method: http.MethodPut, body: reader, optHeader: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } // ci put object from local file func (s *CIService) PutFromFile(ctx context.Context, name string, filePath string, opt *ObjectPutOptions) (*ImageProcessResult, *Response, error) { fd, err := os.Open(filePath) if err != nil { return nil, nil, err } defer fd.Close() return s.Put(ctx, name, fd, opt) } // 基本图片处理 https://cloud.tencent.com/document/product/460/36540 // 盲水印-下载时添加 https://cloud.tencent.com/document/product/460/19017 func (s *CIService) Get(ctx context.Context, name string, operation string, opt *ObjectGetOptions, id ...string) (*Response, error) { var u string if len(id) == 1 { u = fmt.Sprintf("/%s?versionId=%s&%s", encodeURIComponent(name), id[0], operation) } else if len(id) == 0 { u = fmt.Sprintf("/%s?%s", encodeURIComponent(name), operation) } else { return nil, errors.New("wrong params") } sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: u, method: http.MethodGet, optQuery: opt, optHeader: opt, disableCloseBody: true, } resp, err := s.client.send(ctx, &sendOpt) if opt != nil && opt.Listener != nil { if err == nil && resp != nil { if totalBytes, e := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64); e == nil { resp.Body = TeeReader(resp.Body, nil, totalBytes, opt.Listener) } } } return resp, err } func (s *CIService) GetToFile(ctx context.Context, name, localpath, operation string, opt *ObjectGetOptions, id ...string) (*Response, error) { resp, err := s.Get(ctx, name, operation, opt, id...) if err != nil { return resp, err } defer resp.Body.Close() // If file exist, overwrite it fd, err := os.OpenFile(localpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660) if err != nil { return resp, err } _, err = io.Copy(fd, resp.Body) fd.Close() if err != nil { return resp, err } return resp, nil } type GetQRcodeResult struct { XMLName xml.Name `xml:"Response"` CodeStatus int `xml:"CodeStatus,omitempty"` QRcodeInfo *QRcodeInfo `xml:"QRcodeInfo,omitempty"` ResultImage string `xml:"ResultImage,omitempty"` } // 二维码识别-下载时识别 https://cloud.tencent.com/document/product/436/54070 func (s *CIService) GetQRcode(ctx context.Context, name string, cover int, opt *ObjectGetOptions, id ...string) (*GetQRcodeResult, *Response, error) { var u string if len(id) == 1 { u = fmt.Sprintf("/%s?versionId=%s&ci-process=QRcode&cover=%v", encodeURIComponent(name), id[0], cover) } else if len(id) == 0 { u = fmt.Sprintf("/%s?ci-process=QRcode&cover=%v", encodeURIComponent(name), cover) } else { return nil, nil, errors.New("wrong params") } var res GetQRcodeResult sendOpt := sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: u, method: http.MethodGet, optQuery: opt, optHeader: opt, result: &res, } resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } type GenerateQRcodeOptions struct { QRcodeContent string `url:"qrcode-content,omitempty"` Mode int `url:"mode,omitempty"` Width int `url:"width,omitempty"` } type GenerateQRcodeResult struct { XMLName xml.Name `xml:"Response"` ResultImage string `xml:"ResultImage,omitempty"` } // 二维码生成 https://cloud.tencent.com/document/product/436/54071 func (s *CIService) GenerateQRcode(ctx context.Context, opt *GenerateQRcodeOptions) (*GenerateQRcodeResult, *Response, error) { var res GenerateQRcodeResult sendOpt := &sendOptions{ baseURL: s.client.BaseURL.BucketURL, uri: "/?ci-process=qrcode-generate", method: http.MethodGet, optQuery: opt, result: &res, } resp, err := s.client.send(ctx, sendOpt) return &res, resp, err } func (s *CIService) GenerateQRcodeToFile(ctx context.Context, filePath string, opt *GenerateQRcodeOptions) (*GenerateQRcodeResult, *Response, error) { res, resp, err := s.GenerateQRcode(ctx, opt) if err != nil { return res, resp, err } // If file exist, overwrite it fd, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660) if err != nil { return res, resp, err } defer fd.Close() bs, err := base64.StdEncoding.DecodeString(res.ResultImage) if err != nil { return res, resp, err } fb := bytes.NewReader(bs) _, err = io.Copy(fd, fb) return res, resp, err } // 开通 Guetzli 压缩 https://cloud.tencent.com/document/product/460/30112 func (s *CIService) PutGuetzli(ctx context.Context) (*Response, error) { sendOpt := &sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/?guetzli", method: http.MethodPut, } resp, err := s.client.send(ctx, sendOpt) return resp, err } type GetGuetzliResult struct { XMLName xml.Name `xml:"GuetzliStatus"` GuetzliStatus string `xml:",chardata"` } // 查询 Guetzli 状态 https://cloud.tencent.com/document/product/460/30111 func (s *CIService) GetGuetzli(ctx context.Context) (*GetGuetzliResult, *Response, error) { var res GetGuetzliResult sendOpt := &sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/?guetzli", method: http.MethodGet, result: &res, } resp, err := s.client.send(ctx, sendOpt) return &res, resp, err } // 关闭 Guetzli 压缩 https://cloud.tencent.com/document/product/460/30113 func (s *CIService) DeleteGuetzli(ctx context.Context) (*Response, error) { sendOpt := &sendOptions{ baseURL: s.client.BaseURL.CIURL, uri: "/?guetzli", method: http.MethodDelete, } resp, err := s.client.send(ctx, sendOpt) return resp, err }