package datares import ( "bytes" "fmt" "image" "image/gif" "image/jpeg" "image/png" "net/http" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "github.com/qiniu/api.v7/storage" ) const ( qiniuTokenExpires = 300 // 七牛TOKEN有效时间,5分钟 MainImgWidth = 800 MainImgHeight = 800 ) type UploadResTokenInfo struct { Token string `json:"token,omitempty"` Expires uint64 `json:"expires,omitempty"` FileName string `json:"fileName,omitempty"` Hit bool `json:"hit,omitempty"` Img string `json:"img,omitempty"` } func Binary2Image(binaryData []byte, mimeType string) (img image.Image, outMimeType string, err error) { if mimeType == "" { mimeType = http.DetectContentType(binaryData) } switch mimeType { case model.MimeTypeJpeg: img, err = jpeg.Decode(bytes.NewReader(binaryData)) case model.MimeTypePng: img, err = png.Decode(bytes.NewReader(binaryData)) case model.MimeTypeGif: img, err = gif.Decode(bytes.NewReader(binaryData)) } return img, mimeType, err } func GetQiniuUploadToken(ctx *jxcontext.Context, suffix, hashCode string) (upTokenInfo *UploadResTokenInfo, err error) { imgURL := "" if hashCode != "" { imgURL, _ = GetDataResource(ctx, hashCode) } putPolicy := storage.PutPolicy{ Scope: globals.QiniuBucket, Expires: qiniuTokenExpires, } upTokenInfo = &UploadResTokenInfo{ Token: putPolicy.UploadToken(api.QiniuAPI), Expires: putPolicy.Expires, FileName: jxutils.GenPicFileName(suffix), Hit: imgURL != "", Img: imgURL, } return upTokenInfo, err } // 此函数要求resBinary不能空,mimeType与hashCode必须是正确的 func RegisterDataResource(ctx *jxcontext.Context, name, resourceURL, mimeType, hashCode string, resBinary []byte, imgType int, isAsyncUpload2Vendor bool) (dataRes *model.DataResource, err error) { globals.SugarLogger.Debugf("RegisterDataResource, name:%s, resourceURL:%s, mimeType:%s, hashCode:%s, imgType:%d, isAsyncUpload2Vendor;%t", name, resourceURL, mimeType, hashCode, imgType, isAsyncUpload2Vendor) if model.ValidMimeTypes[mimeType] == 0 { return nil, fmt.Errorf("MIME type:%s非法,当前只支持:%s", mimeType, model.GetValidMimeTypeDesc()) } img, _, err := Binary2Image(resBinary, mimeType) if err != nil { return nil, err } if imgType == model.ImgTypeMain { if img.Bounds().Dx() != MainImgWidth || img.Bounds().Dy() != MainImgHeight { return nil, fmt.Errorf("图片大小:%dx%d非法,要求必须:%dx%d", img.Bounds().Dx(), img.Bounds().Dy(), MainImgWidth, MainImgHeight) } } dataRes = &model.DataResource{ Name: name, HashCode: hashCode, ResourceType: mimeType, MainURL: resourceURL, UseType: int8(imgType), } vendorID := jxutils.GuessDataResourceVendor(resourceURL) switch vendorID { case model.VendorIDQiNiuCloud: dataRes.QiniuURL = resourceURL case model.VendorIDEBAI: dataRes.EbaiURL = resourceURL } dao.WrapAddIDCULEntity(dataRes, ctx.GetUserName()) if err = dao.CreateEntity(dao.GetDB(), dataRes); err != nil { if dao.IsDuplicateError(err) { dataRes, err = dao.GetDataResource(dao.GetDB(), dataRes.HashCode, dataRes.MainURL) } else { dataRes = nil } return dataRes, err } if imgType > 0 { if globals.EnableStoreWrite { // 忽略上传错误 UploadImage2Vendors(ctx, nil, dataRes, resBinary, isAsyncUpload2Vendor) } } return dataRes, err } func TryRegisterDataResource(ctx *jxcontext.Context, name, resourceURL string, imgType int, isAsyncUpload2Vendor bool) (dataRes *model.DataResource, err error) { globals.SugarLogger.Debugf("TryRegisterDataResource, name:%s, resourceURL:%s, imgType:%d, isAsyncUpload2Vendor;%t", name, resourceURL, imgType, isAsyncUpload2Vendor) dataRes = &model.DataResource{ MainURL: resourceURL, } err = dao.GetEntity(dao.GetDB(), dataRes, "MainURL") if err != nil { if !dao.IsNoRowsError(err) { return nil, err } } else { return dataRes, nil } resBinary, hashCode, err := jxutils.DownloadFileByURL(resourceURL) if err != nil { return nil, err } return RegisterDataResource(ctx, name, resourceURL, http.DetectContentType(resBinary), hashCode, resBinary, imgType, isAsyncUpload2Vendor) } func GetDataResource(ctx *jxcontext.Context, hashCode string) (resourceURL string, err error) { db := dao.GetDB() dataRes, err := dao.GetDataResource(db, hashCode, "") if err != nil { if dao.IsNoRowsError(err) { err = nil } } else { resourceURL = dataRes.MainURL } return resourceURL, err } // 这个函数,可能部分平台成功,部分失败 func UploadImage2Vendors(ctx *jxcontext.Context, parentTask tasksch.ITask, dataRes *model.DataResource, imgData []byte, isAsync bool) (hint string, err error) { // var vendorIDs []int // if dataRes.EbaiURL == "" { // vendorIDs = append(vendorIDs, model.VendorIDEBAI) // } // if dataRes.MtwmURL == "" { // vendorIDs = append(vendorIDs, model.VendorIDMTWM) // } // if dataRes.JdsURL == "" { // vendorIDs = append(vendorIDs, model.VendorIDJDShop) // } // if len(vendorIDs) > 0 { // imgName := jxutils.GetShortNameFromURL(dataRes.MainURL) // task := tasksch.NewSeqTask(fmt.Sprintf("上传图片至平台1:%s,%s", dataRes.Name, dataRes.MainURL), ctx, // func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // switch step { // case 0: // if imgData == nil { // if imgData, _, err = jxutils.DownloadFileByURL(dataRes.MainURL); err != nil { // return nil, err // } // } // case 1: // uploadTask := tasksch.NewParallelTask(fmt.Sprintf("上传图片至平台2:%s,%s", dataRes.Name, imgName), // tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // vendorID := batchItemList[0].(int) // if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil { // // TODO vendorOrgCode // imgHint, err2 := handler.UploadImg(ctx, "", dataRes.MainURL, imgData, imgName, int(dataRes.UseType)) // if err = err2; err == nil { // retVal = [][]interface{}{ // []interface{}{ // vendorID, // imgHint, // }, // } // } // } // return retVal, err // }, vendorIDs) // tasksch.HandleTask(uploadTask, task, false).Run() // resultList, err2 := uploadTask.GetResult(0) // err = err2 // if len(resultList) > 0 { // db := dao.GetDB() // for _, v := range resultList { // result := v.([]interface{}) // vendorID := result[0].(int) // imgHint := result[1].(string) // updateField := "" // if vendorID == model.VendorIDEBAI { // dataRes.EbaiURL = imgHint // updateField = "EbaiURL" // } else if vendorID == model.VendorIDMTWM { // dataRes.MtwmURL = imgHint // updateField = "MtwmURL" // } // // else if vendorID == model.VendorIDJDShop { // // dataRes.JdsURL = imgHint // // updateField = "JdsURL" // // } // dao.UpdateEntity(db, dataRes, updateField) // } // } // } // return result, err // }, 2) // tasksch.HandleTask(task, parentTask, false).Run() // if !isAsync { // if _, err = task.GetResult(0); err == nil { // hint = "1" // } // } else { // hint = task.GetID() // } // } return hint, err } // func UploadImg2Platforms(ctx *jxcontext.Context, parentTask tasksch.ITask, imgURL string, imgData []byte, imgName string) (imgHintMap map[int]string, err error) { // task := tasksch.NewParallelTask("UploadImg2Platforms", nil, ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // vendorID := batchItemList[0].(int) // if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil { // imgHint, err2 := handler.UploadImg(ctx, imgURL, imgData, imgName) // if err = err2; err == nil { // return [][]interface{}{ // []interface{}{ // vendorID, // imgHint, // }, // }, nil // } // } // return nil, err // }, []int{model.VendorIDEBAI}) // tasksch.HandleTask(task, parentTask, false).Run() // resultList, err := task.GetResult(0) // if err == nil { // imgHintMap = make(map[int]string) // for _, v := range resultList { // vList := v.([]interface{}) // imgHintMap[vList[0].(int)] = vList[1].(string) // } // } // return imgHintMap, err // }