ci 内容审核
This commit is contained in:
145
ci.go
145
ci.go
@@ -4,15 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CIService service
|
||||||
|
|
||||||
type PicOperations struct {
|
type PicOperations struct {
|
||||||
IsPicInfo int `json:"is_pic_info,omitempty"`
|
IsPicInfo int `json:"is_pic_info,omitempty"`
|
||||||
Rules []PicOperationsRules `json:"rules,omitemtpy"`
|
Rules []PicOperationsRules `json:"rules,omitemtpy"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicOperationsRules struct {
|
type PicOperationsRules struct {
|
||||||
Bucket string `json:"bucket,omitempty"`
|
Bucket string `json:"bucket,omitempty"`
|
||||||
FileId string `json:"fileid"`
|
FileId string `json:"fileid"`
|
||||||
@@ -20,6 +20,9 @@ type PicOperationsRules struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func EncodePicOperations(pic *PicOperations) string {
|
func EncodePicOperations(pic *PicOperations) string {
|
||||||
|
if pic == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
bs, err := json.Marshal(pic)
|
bs, err := json.Marshal(pic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
@@ -27,18 +30,16 @@ func EncodePicOperations(pic *PicOperations) string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CloudImageReuslt struct {
|
type ImageProcessResult struct {
|
||||||
XMLName xml.Name `xml:"UploadResult"`
|
XMLName xml.Name `xml:"UploadResult"`
|
||||||
OriginalInfo *PicOriginalInfo `xml:"OriginalInfo,omitempty"`
|
OriginalInfo *PicOriginalInfo `xml:"OriginalInfo,omitempty"`
|
||||||
ProcessObject *PicProcessObject `xml:"ProcessResults>Object,omitempty"`
|
ProcessObject *PicProcessObject `xml:"ProcessResults>Object,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicOriginalInfo struct {
|
type PicOriginalInfo struct {
|
||||||
Key string `xml:"Key,omitempty"`
|
Key string `xml:"Key,omitempty"`
|
||||||
Location string `xml:"Location,omitempty"`
|
Location string `xml:"Location,omitempty"`
|
||||||
ImageInfo *PicImageInfo `xml:"ImageInfo,omitempty"`
|
ImageInfo *PicImageInfo `xml:"ImageInfo,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicImageInfo struct {
|
type PicImageInfo struct {
|
||||||
Format string `xml:"Format,omitempty"`
|
Format string `xml:"Format,omitempty"`
|
||||||
Width int `xml:"Width,omitempty"`
|
Width int `xml:"Width,omitempty"`
|
||||||
@@ -46,7 +47,6 @@ type PicImageInfo struct {
|
|||||||
Size int `xml:"Size,omitempty"`
|
Size int `xml:"Size,omitempty"`
|
||||||
Quality int `xml:"Quality,omitempty"`
|
Quality int `xml:"Quality,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicProcessObject struct {
|
type PicProcessObject struct {
|
||||||
Key string `xml:"Key,omitempty"`
|
Key string `xml:"Key,omitempty"`
|
||||||
Location string `xml:"Location,omitempty"`
|
Location string `xml:"Location,omitempty"`
|
||||||
@@ -57,24 +57,42 @@ type PicProcessObject struct {
|
|||||||
Quality int `xml:"Quality,omitempty"`
|
Quality int `xml:"Quality,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CloudImageOptions struct {
|
type picOperationsHeader struct {
|
||||||
PicOperations string `header:"Pic-Operations" xml:"-" url:"-"`
|
PicOperations string `header:"Pic-Operations" xml:"-" url:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ObjectService) PostCI(ctx context.Context, name string, opt *CloudImageOptions) (*CloudImageReuslt, *Response, error) {
|
type ImageProcessOptions = PicOperations
|
||||||
var res CloudImageReuslt
|
|
||||||
|
// 云上数据处理 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{
|
sendOpt := sendOptions{
|
||||||
baseURL: s.client.BaseURL.BucketURL,
|
baseURL: s.client.BaseURL.BucketURL,
|
||||||
uri: "/" + encodeURIComponent(name) + "?image_process",
|
uri: "/" + encodeURIComponent(name) + "?image_process",
|
||||||
method: http.MethodPost,
|
method: http.MethodPost,
|
||||||
optHeader: opt,
|
optHeader: header,
|
||||||
result: &res,
|
result: &res,
|
||||||
}
|
}
|
||||||
resp, err := s.client.send(ctx, &sendOpt)
|
resp, err := s.client.send(ctx, &sendOpt)
|
||||||
return &res, resp, err
|
return &res, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type CloudImageRecognitionInfo struct {
|
type ImageRecognitionOptions struct {
|
||||||
|
CIProcess string `url:"ci-process,omitempty"`
|
||||||
|
DetectType string `url:"detect-type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageRecognitionResult struct {
|
||||||
|
XMLName xml.Name `xml:"RecognitionResult"`
|
||||||
|
PornInfo *RecognitionInfo `xml:"PornInfo,omitempty"`
|
||||||
|
TerroristInfo *RecognitionInfo `xml:"TerroristInfo,omitempty"`
|
||||||
|
PoliticsInfo *RecognitionInfo `xml:"PoliticsInfo,omitempty"`
|
||||||
|
AdsInfo *RecognitionInfo `xml:"AdsInfo,omitempty"`
|
||||||
|
}
|
||||||
|
type RecognitionInfo struct {
|
||||||
Code int `xml:"Code,omitempty"`
|
Code int `xml:"Code,omitempty"`
|
||||||
Msg string `xml:"Msg,omitempty"`
|
Msg string `xml:"Msg,omitempty"`
|
||||||
HitFlag int `xml:"HitFlag,omitempty"`
|
HitFlag int `xml:"HitFlag,omitempty"`
|
||||||
@@ -83,18 +101,99 @@ type CloudImageRecognitionInfo struct {
|
|||||||
Count int `xml:"Count,omitempty"`
|
Count int `xml:"Count,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CloudImageRecognitionResult struct {
|
// 图片审核 https://cloud.tencent.com/document/product/460/37318
|
||||||
PornInfo *CloudImageRecognitionInfo `xml:"PornInfo,omitempty"`
|
func (s *CIService) ImageRecognition(ctx context.Context, name string, opt *ImageRecognitionOptions) (*ImageRecognitionResult, *Response, error) {
|
||||||
TerroristInfo *CloudImageRecognitionInfo `xml:"TerroristInfo,omitempty"`
|
if opt != nil && opt.CIProcess == "" {
|
||||||
PoliticsInfo *CloudImageRecognitionInfo `xml:"PoliticsInfo,omitempty"`
|
opt.CIProcess = "sensitive-content-recognition"
|
||||||
AdsInfo *CloudImageRecognitionInfo `xml:"AdsInfo,omitempty"`
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRecognitionResult(body io.ReadCloser) *CloudImageRecognitionResult {
|
type PutVideoAuditingJobOptions struct {
|
||||||
var res CloudImageRecognitionResult
|
XMLName xml.Name `xml:"Request"`
|
||||||
err := xml.NewDecoder(body).Decode(&res)
|
InputObject string `xml:"Input>Object"`
|
||||||
if err != nil && err != io.EOF {
|
Conf *VideoAuditingJobConf `xml:"Conf"`
|
||||||
return nil
|
}
|
||||||
}
|
type VideoAuditingJobConf struct {
|
||||||
return &res
|
DetectType string `xml:",omitempty"`
|
||||||
|
Snapshot *PutVideoAuditingJobSnapshot `xml:",omitempty"`
|
||||||
|
Callback string `xml:",omitempty"`
|
||||||
|
}
|
||||||
|
type PutVideoAuditingJobSnapshot struct {
|
||||||
|
Mode string `xml:",omitempty"`
|
||||||
|
Count int `xml:",omitempty"`
|
||||||
|
TimeInterval float32 `xml:",omitempty"`
|
||||||
|
Start float32 `xml:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetVideoAuditingJobResult struct {
|
||||||
|
XMLName xml.Name `xml:"Response"`
|
||||||
|
JobsDetail *VideoAuditingJobDetail `xml:",omitempty"`
|
||||||
|
NonExistJobIds string `xml:",omitempty"`
|
||||||
|
}
|
||||||
|
type VideoAuditingJobDetail 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"`
|
||||||
|
SnapshotCount 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"`
|
||||||
|
}
|
||||||
|
type GetVideoAuditingJobSnapshot struct {
|
||||||
|
Url string `xml:",omitempty"`
|
||||||
|
PornInfo *RecognitionInfo `xml:",omitempty"`
|
||||||
|
TerrorismInfo *RecognitionInfo `xml:",omitempty"`
|
||||||
|
PoliticsInfo *RecognitionInfo `xml:",omitempty"`
|
||||||
|
AdsInfo *RecognitionInfo `xml:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
8
cos.go
8
cos.go
@@ -42,6 +42,8 @@ type BaseURL struct {
|
|||||||
ServiceURL *url.URL
|
ServiceURL *url.URL
|
||||||
// 访问 job API 的基础 URL (不包含 path 部分): http://example.com
|
// 访问 job API 的基础 URL (不包含 path 部分): http://example.com
|
||||||
BatchURL *url.URL
|
BatchURL *url.URL
|
||||||
|
// 访问 CI 的基础 URL
|
||||||
|
CIURL *url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBucketURL 生成 BaseURL 所需的 BucketURL
|
// NewBucketURL 生成 BaseURL 所需的 BucketURL
|
||||||
@@ -82,6 +84,7 @@ type Client struct {
|
|||||||
Bucket *BucketService
|
Bucket *BucketService
|
||||||
Object *ObjectService
|
Object *ObjectService
|
||||||
Batch *BatchService
|
Batch *BatchService
|
||||||
|
CI *CIService
|
||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
@@ -99,6 +102,7 @@ func NewClient(uri *BaseURL, httpClient *http.Client) *Client {
|
|||||||
baseURL.BucketURL = uri.BucketURL
|
baseURL.BucketURL = uri.BucketURL
|
||||||
baseURL.ServiceURL = uri.ServiceURL
|
baseURL.ServiceURL = uri.ServiceURL
|
||||||
baseURL.BatchURL = uri.BatchURL
|
baseURL.BatchURL = uri.BatchURL
|
||||||
|
baseURL.CIURL = uri.CIURL
|
||||||
}
|
}
|
||||||
if baseURL.ServiceURL == nil {
|
if baseURL.ServiceURL == nil {
|
||||||
baseURL.ServiceURL, _ = url.Parse(defaultServiceBaseURL)
|
baseURL.ServiceURL, _ = url.Parse(defaultServiceBaseURL)
|
||||||
@@ -114,6 +118,7 @@ func NewClient(uri *BaseURL, httpClient *http.Client) *Client {
|
|||||||
c.Bucket = (*BucketService)(&c.common)
|
c.Bucket = (*BucketService)(&c.common)
|
||||||
c.Object = (*ObjectService)(&c.common)
|
c.Object = (*ObjectService)(&c.common)
|
||||||
c.Batch = (*BatchService)(&c.common)
|
c.Batch = (*BatchService)(&c.common)
|
||||||
|
c.CI = (*CIService)(&c.common)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,9 +249,6 @@ func (c *Client) send(ctx context.Context, opt *sendOptions) (resp *Response, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp, err = c.doAPI(ctx, req, opt.result, !opt.disableCloseBody)
|
resp, err = c.doAPI(ctx, req, opt.result, !opt.disableCloseBody)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func setup() {
|
|||||||
server = httptest.NewServer(mux)
|
server = httptest.NewServer(mux)
|
||||||
|
|
||||||
u, _ := url.Parse(server.URL)
|
u, _ := url.Parse(server.URL)
|
||||||
client = NewClient(&BaseURL{u, u, u}, nil)
|
client = NewClient(&BaseURL{u, u, u, u}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// teardown closes the test HTTP server.
|
// teardown closes the test HTTP server.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -48,7 +47,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
pic := &cos.PicOperations{
|
opt := &cos.ImageProcessOptions{
|
||||||
IsPicInfo: 1,
|
IsPicInfo: 1,
|
||||||
Rules: []cos.PicOperationsRules{
|
Rules: []cos.PicOperationsRules{
|
||||||
{
|
{
|
||||||
@@ -57,12 +56,8 @@ func main() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
opt := &cos.CloudImageOptions{
|
|
||||||
PicOperations: cos.EncodePicOperations(pic),
|
|
||||||
}
|
|
||||||
name := "test.jpg"
|
name := "test.jpg"
|
||||||
res, _, err := c.Object.PostCI(context.Background(), name, opt)
|
res, _, err := c.CI.ImageProcess(context.Background(), name, opt)
|
||||||
data, _ := xml.Marshal(res)
|
|
||||||
fmt.Printf("%+v\n", string(data))
|
|
||||||
log_status(err)
|
log_status(err)
|
||||||
|
fmt.Printf("%+v\n", res)
|
||||||
}
|
}
|
||||||
@@ -45,18 +45,12 @@ func main() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
opt := &cos.ObjectGetOptions{
|
opt := &cos.ImageRecognitionOptions{
|
||||||
CIProcess: "sensitive-content-recognition",
|
DetectType: "porn,terrorist,politics",
|
||||||
CIDetectType: "porn,terrorist,politics,ads",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case1 Download object into ReadCloser(). the body needs to be closed
|
|
||||||
name := "test.jpg"
|
name := "test.jpg"
|
||||||
resp, err := c.Object.Get(context.Background(), name, opt)
|
res, _, err := c.CI.ImageRecognition(context.Background(), name, opt)
|
||||||
log_status(err)
|
log_status(err)
|
||||||
resp.Body.Close()
|
fmt.Printf("%+v\n", res)
|
||||||
res := cos.GetRecognitionResult(resp.Body)
|
|
||||||
if res != nil {
|
|
||||||
fmt.Printf("%+v\n", res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
71
example/object/ci_video_auditing_job.go
Normal file
71
example/object/ci_video_auditing_job.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tencentyun/cos-go-sdk-v5"
|
||||||
|
"github.com/tencentyun/cos-go-sdk-v5/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
func log_status(err error) {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cos.IsNotFoundError(err) {
|
||||||
|
// WARN
|
||||||
|
fmt.Println("WARN: Resource is not existed")
|
||||||
|
} else if e, ok := cos.IsCOSError(err); ok {
|
||||||
|
fmt.Printf("ERROR: Code: %v\n", e.Code)
|
||||||
|
fmt.Printf("ERROR: Message: %v\n", e.Message)
|
||||||
|
fmt.Printf("ERROR: Resource: %v\n", e.Resource)
|
||||||
|
fmt.Printf("ERROR: RequestId: %v\n", e.RequestID)
|
||||||
|
// ERROR
|
||||||
|
} else {
|
||||||
|
fmt.Printf("ERROR: %v\n", err)
|
||||||
|
// ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bu, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com")
|
||||||
|
cu, _ := url.Parse("https://test-1259654469.ci.ap-guangzhou.myqcloud.com")
|
||||||
|
b := &cos.BaseURL{BucketURL: bu, CIURL: cu}
|
||||||
|
c := cos.NewClient(b, &http.Client{
|
||||||
|
Transport: &cos.AuthorizationTransport{
|
||||||
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
Transport: &debug.DebugRequestTransport{
|
||||||
|
RequestHeader: true,
|
||||||
|
RequestBody: true,
|
||||||
|
ResponseHeader: true,
|
||||||
|
ResponseBody: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
opt := &cos.PutVideoAuditingJobOptions{
|
||||||
|
InputObject: "demo.mp4",
|
||||||
|
Conf: &cos.VideoAuditingJobConf{
|
||||||
|
DetectType: "Porn,Terrorism,Politics,Ads",
|
||||||
|
Snapshot: &cos.PutVideoAuditingJobSnapshot{
|
||||||
|
Mode: "Interval",
|
||||||
|
Start: 0.5,
|
||||||
|
TimeInterval: 50.5,
|
||||||
|
Count: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
res, _, err := c.CI.PutVideoAuditingJob(context.Background(), opt)
|
||||||
|
log_status(err)
|
||||||
|
fmt.Printf("%+v\n", res)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
res2, _, err := c.CI.GetVideoAuditingJob(context.Background(), res.JobsDetail.JobId)
|
||||||
|
log_status(err)
|
||||||
|
fmt.Printf("%+v\n", res2)
|
||||||
|
}
|
||||||
20
object.go
20
object.go
@@ -35,10 +35,6 @@ type ObjectGetOptions struct {
|
|||||||
XCosSSECustomerKeyMD5 string `header:"x-cos-server-side-encryption-customer-key-MD5,omitempty" url:"-" xml:"-"`
|
XCosSSECustomerKeyMD5 string `header:"x-cos-server-side-encryption-customer-key-MD5,omitempty" url:"-" xml:"-"`
|
||||||
|
|
||||||
XCosTrafficLimit int `header:"x-cos-traffic-limit,omitempty" url:"-" xml:"-"`
|
XCosTrafficLimit int `header:"x-cos-traffic-limit,omitempty" url:"-" xml:"-"`
|
||||||
|
|
||||||
// CI 图片审核
|
|
||||||
CIProcess string `header:"-" url:"ci-process" xml:"-"`
|
|
||||||
CIDetectType string `header:"-" url:"detect-type" xml:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// presignedURLTestingOptions is the opt of presigned url
|
// presignedURLTestingOptions is the opt of presigned url
|
||||||
@@ -501,6 +497,7 @@ type Chunk struct {
|
|||||||
OffSet int64
|
OffSet int64
|
||||||
Size int64
|
Size int64
|
||||||
Done bool
|
Done bool
|
||||||
|
ETag string
|
||||||
}
|
}
|
||||||
|
|
||||||
// jobs
|
// jobs
|
||||||
@@ -662,8 +659,9 @@ func (s *ObjectService) checkUploadedParts(ctx context.Context, name, UploadID,
|
|||||||
defer fd.Close()
|
defer fd.Close()
|
||||||
// 某个分块出错, 重置chunks
|
// 某个分块出错, 重置chunks
|
||||||
ret := func(e error) error {
|
ret := func(e error) error {
|
||||||
for _, chunk := range chunks {
|
for i, _ := range chunks {
|
||||||
chunk.Done = false
|
chunks[i].Done = false
|
||||||
|
chunks[i].ETag = ""
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
@@ -683,6 +681,7 @@ func (s *ObjectService) checkUploadedParts(ctx context.Context, name, UploadID,
|
|||||||
return ret(errors.New(fmt.Sprintf("CheckSum Failed in Part[%d]", part.PartNumber)))
|
return ret(errors.New(fmt.Sprintf("CheckSum Failed in Part[%d]", part.PartNumber)))
|
||||||
}
|
}
|
||||||
chunks[partNumber].Done = true
|
chunks[partNumber].Done = true
|
||||||
|
chunks[partNumber].ETag = part.ETag
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -706,6 +705,7 @@ func (s *ObjectService) Upload(ctx context.Context, name string, filepath string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
// filesize=0 , use simple upload
|
||||||
if partNum == 0 {
|
if partNum == 0 {
|
||||||
var opt0 *ObjectPutOptions
|
var opt0 *ObjectPutOptions
|
||||||
if opt.OptIni != nil {
|
if opt.OptIni != nil {
|
||||||
@@ -787,7 +787,13 @@ func (s *ObjectService) Upload(ctx context.Context, name string, filepath string
|
|||||||
close(chjobs)
|
close(chjobs)
|
||||||
|
|
||||||
// 5.Recv the resp etag to complete
|
// 5.Recv the resp etag to complete
|
||||||
for i := 1; i <= partNum; i++ {
|
for i := 0; i < partNum; i++ {
|
||||||
|
if chunks[i].Done {
|
||||||
|
optcom.Parts = append(optcom.Parts, Object{
|
||||||
|
PartNumber: chunks[i].Number, ETag: chunks[i].ETag},
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
res := <-chresults
|
res := <-chresults
|
||||||
// Notice one part fail can not get the etag according.
|
// Notice one part fail can not get the etag according.
|
||||||
if res.Resp == nil || res.err != nil {
|
if res.Resp == nil || res.err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user