Skip to content

Commit

Permalink
add CI QRCode && Update CI
Browse files Browse the repository at this point in the history
  • Loading branch information
jojoliang committed Apr 27, 2021
1 parent e8b4da1 commit e2bf821
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 243 deletions.
21 changes: 19 additions & 2 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ var needSignHeaders = map[string]bool{
"x-cos-object-type": true,
}

var ciParameters = map[string]bool{
"imagemogr2/": true,
"watermark/": true,
"imageview2/": true,
}

func safeURLEncode(s string) string {
s = encodeURIComponent(s)
s = strings.Replace(s, "!", "%21", -1)
Expand Down Expand Up @@ -205,8 +211,10 @@ func genFormatParameters(parameters url.Values) (formatParameters string, signed
for key, values := range parameters {
key = strings.ToLower(key)
for _, value := range values {
ps.Add(key, value)
signedParameterList = append(signedParameterList, key)
if !isCIParameter(key) {
ps.Add(key, value)
signedParameterList = append(signedParameterList, key)
}
}
}
//formatParameters = strings.ToLower(ps.Encode())
Expand Down Expand Up @@ -246,6 +254,15 @@ func calHMACDigest(key, msg, signMethod string) []byte {
return h.Sum(nil)
}

func isCIParameter(key string) bool {
for k, v := range ciParameters {
if strings.HasPrefix(key, k) && v {
return true
}
}
return false
}

func isSignHeader(key string) bool {
for k, v := range needSignHeaders {
if key == k && v {
Expand Down
175 changes: 162 additions & 13 deletions ci.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package cos

import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"hash/crc64"
"io"
"net/http"
"os"
"strconv"
)

type CIService service
Expand Down Expand Up @@ -54,15 +58,24 @@ type PicImageInfo struct {
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"`
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 {
Expand Down Expand Up @@ -110,9 +123,10 @@ type RecognitionInfo struct {
}

// 图片审核 https://cloud.tencent.com/document/product/460/37318
func (s *CIService) ImageRecognition(ctx context.Context, name string, opt *ImageRecognitionOptions) (*ImageRecognitionResult, *Response, error) {
if opt != nil && opt.CIProcess == "" {
opt.CIProcess = "sensitive-content-recognition"
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{
Expand Down Expand Up @@ -153,6 +167,7 @@ type PutVideoAuditingJobResult struct {
} `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{
Expand Down Expand Up @@ -194,6 +209,7 @@ type GetVideoAuditingJobSnapshot struct {
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{
Expand All @@ -206,7 +222,8 @@ func (s *CIService) GetVideoAuditingJob(ctx context.Context, jobid string) (*Get
return &res, resp, err
}

// ci put https://cloud.tencent.com/document/product/460/18147
// 图片持久化处理-上传时处理 https://cloud.tencent.com/document/product/460/18147
// 二维码识别-上传时识别 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")
Expand Down Expand Up @@ -257,3 +274,135 @@ func (s *CIService) PutFromFile(ctx context.Context, name string, filePath strin

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
}
7 changes: 7 additions & 0 deletions ci_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type CreateDocProcessJobsResult struct {
JobsDetail DocProcessJobDetail `xml:"JobsDetail,omitempty"`
}

// 创建文档预览任务 https://cloud.tencent.com/document/product/436/54056
func (s *CIService) CreateDocProcessJobs(ctx context.Context, opt *CreateDocProcessJobsOptions) (*CreateDocProcessJobsResult, *Response, error) {
var res CreateDocProcessJobsResult
sendOpt := sendOptions{
Expand All @@ -92,6 +93,7 @@ type DescribeDocProcessJobResult struct {
NonExistJobIds string `xml:"NonExistJobIds,omitempty"`
}

// 查询文档预览任务 https://cloud.tencent.com/document/product/436/54095
func (s *CIService) DescribeDocProcessJob(ctx context.Context, jobid string) (*DescribeDocProcessJobResult, *Response, error) {
var res DescribeDocProcessJobResult
sendOpt := sendOptions{
Expand Down Expand Up @@ -121,6 +123,7 @@ type DescribeDocProcessJobsResult struct {
NextToken string `xml:"NextToken,omitempty"`
}

// 拉取符合条件的文档预览任务 https://cloud.tencent.com/document/product/436/54096
func (s *CIService) DescribeDocProcessJobs(ctx context.Context, opt *DescribeDocProcessJobsOptions) (*DescribeDocProcessJobsResult, *Response, error) {
var res DescribeDocProcessJobsResult
sendOpt := sendOptions{
Expand Down Expand Up @@ -169,6 +172,7 @@ type DocProcessQueueNotifyConfig struct {
Event string `xml:"Event,omitempty"`
}

// 查询文档预览队列 https://cloud.tencent.com/document/product/436/54055
func (s *CIService) DescribeDocProcessQueues(ctx context.Context, opt *DescribeDocProcessQueuesOptions) (*DescribeDocProcessQueuesResult, *Response, error) {
var res DescribeDocProcessQueuesResult
sendOpt := sendOptions{
Expand Down Expand Up @@ -196,6 +200,7 @@ type UpdateDocProcessQueueResult struct {
Queue *DocProcessQueue `xml:"Queue"`
}

// 更新文档预览队列 https://cloud.tencent.com/document/product/436/54094
func (s *CIService) UpdateDocProcessQueue(ctx context.Context, opt *UpdateDocProcessQueueOptions) (*UpdateDocProcessQueueResult, *Response, error) {
var res UpdateDocProcessQueueResult
sendOpt := sendOptions{
Expand Down Expand Up @@ -233,6 +238,7 @@ type DocProcessBucket struct {
AliasBucketId string `xml:"AliasBucketId,omitempty"`
}

// 查询文档预览开通状态 https://cloud.tencent.com/document/product/436/54057
func (s *CIService) DescribeDocProcessBuckets(ctx context.Context, opt *DescribeDocProcessBucketsOptions) (*DescribeDocProcessBucketsResult, *Response, error) {
var res DescribeDocProcessBucketsResult
sendOpt := sendOptions{
Expand All @@ -259,6 +265,7 @@ type DocPreviewOptions struct {
Zoom int `url:"zoom,omitempty"`
}

// 同步请求接口 https://cloud.tencent.com/document/product/436/54058
func (s *CIService) DocPreview(ctx context.Context, name string, opt *DocPreviewOptions) (*Response, error) {
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
Expand Down
27 changes: 23 additions & 4 deletions example/object/ci_put.go → example/CI/ci_QRcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func main() {
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: true,
ResponseBody: false,
},
},
})
Expand All @@ -58,13 +58,32 @@ func main() {
Rules: []cos.PicOperationsRules{
{
FileId: "format.jpg",
Rule: "imageView2/format/png",
Rule: "QRcode/cover/1",
},
},
}
opt.XOptionHeader.Add("Pic-Operations", cos.EncodePicOperations(pic))
name := "test.jpg"
local_filename := "./test.jpg"
_, err := c.Object.PutFromFile(context.Background(), name, local_filename, opt)
local_filename := "./QRcode.jpg"
res, _, err := c.CI.PutFromFile(context.Background(), name, local_filename, opt)
log_status(err)
fmt.Printf("%+v\n", res)
fmt.Printf("%+v\n", res.OriginalInfo)
fmt.Printf("%+v\n", res.ProcessResults)

res2, _, err := c.CI.GetQRcode(context.Background(), name, 0, nil)
log_status(err)
fmt.Printf("%+v\n", res2)

gopt := &cos.GenerateQRcodeOptions{
QRcodeContent: fmt.Sprintf("<%v>", res2.QRcodeInfo.CodeUrl),
Mode: 0,
Width: 200,
}
res3, _, err := c.CI.GenerateQRcode(context.Background(), gopt)
log_status(err)
fmt.Printf("%+v\n", res3)

_, _, err = c.CI.GenerateQRcodeToFile(context.Background(), "./downQRcode.jpg", gopt)
log_status(err)
}
15 changes: 3 additions & 12 deletions example/object/ci_image_process.go → example/CI/ci_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,13 @@ func main() {
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: true,
ResponseBody: false,
},
},
})

opt := &cos.ImageProcessOptions{
IsPicInfo: 1,
Rules: []cos.PicOperationsRules{
{
FileId: "format.jpg",
Rule: "imageView2/format/png",
},
},
}
name := "test.jpg"
res, _, err := c.CI.ImageProcess(context.Background(), name, opt)
filepath := "test.jpg"
_, err := c.CI.GetToFile(context.Background(), name, filepath, "imageMogr2/thumbnail/!50px", nil)
log_status(err)
fmt.Printf("%+v\n", res)
}

0 comments on commit e2bf821

Please sign in to comment.