|
@@ -0,0 +1,370 @@
|
|
|
+package api
|
|
|
+
|
|
|
+import (
|
|
|
+ "box-cost/conf"
|
|
|
+ "box-cost/db/model"
|
|
|
+ "box-cost/log"
|
|
|
+ "fmt"
|
|
|
+ "os"
|
|
|
+ "path"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ "github.com/gin-gonic/gin"
|
|
|
+ "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
|
|
|
+)
|
|
|
+
|
|
|
+func CreateObsClient() (*obs.ObsClient, error) {
|
|
|
+ obsConf := conf.AppConfig.Obs
|
|
|
+ return obs.New(obsConf.AccessKeyId, obsConf.SecrateKey, obsConf.Endpoint)
|
|
|
+}
|
|
|
+
|
|
|
+// u/xxx/img/up/timps.png
|
|
|
+func ServiceObsCreateImagePolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+ body := struct {
|
|
|
+ Ext string
|
|
|
+ }{}
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("参数解析错误!")
|
|
|
+ }
|
|
|
+ if len(body.Ext) < 1 {
|
|
|
+ return nil, NewError("上传文件的扩展名不能为空")
|
|
|
+ }
|
|
|
+
|
|
|
+ fkey := fmt.Sprintf("u/%s/images/uploads/%v.%s", apictx.User.Parent, time.Now().UnixNano(), body.Ext)
|
|
|
+
|
|
|
+ client, err := CreateObsClient()
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("创建ObsClient 失败!")
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ client.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
+ // 除key,policy,signature外,表单上传时的其他参数,支持的值:
|
|
|
+ // acl
|
|
|
+ // cache-control
|
|
|
+ // content-type
|
|
|
+ // content-disposition
|
|
|
+ // content-encoding
|
|
|
+ // expires
|
|
|
+ bucketName := apictx.Svc.Conf.Obs.Bucket
|
|
|
+
|
|
|
+ result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: fkey,
|
|
|
+ Expires: 300,
|
|
|
+ FormParams: map[string]string{
|
|
|
+ "x-obs-acl": "public-read",
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewLogWithError(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ obsConf := conf.AppConfig.Obs
|
|
|
+
|
|
|
+ out := map[string]interface{}{
|
|
|
+ "accessKeyId": obsConf.AccessKeyId,
|
|
|
+ "originPolicy": result.OriginPolicy,
|
|
|
+ "policy": result.Policy,
|
|
|
+ "signature": result.Signature,
|
|
|
+ "host": fmt.Sprintf("//%s.%s", bucketName, obsConf.Endpoint),
|
|
|
+ "key": fkey,
|
|
|
+ }
|
|
|
+ return out, nil
|
|
|
+}
|
|
|
+
|
|
|
+func ServiceObsList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+
|
|
|
+ prefix := c.Query("prefix")
|
|
|
+
|
|
|
+ if len(prefix) < 1 {
|
|
|
+ return nil, NewError("prefix不能为空")
|
|
|
+ }
|
|
|
+
|
|
|
+ client, err := CreateObsClient()
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("创建ObsClient 失败!")
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ client.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
+ bucketName := apictx.Svc.Conf.Obs.Bucket
|
|
|
+ result, err := client.ListObjects(&obs.ListObjectsInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ ListObjsInput: obs.ListObjsInput{
|
|
|
+ Prefix: prefix,
|
|
|
+ Delimiter: "/",
|
|
|
+ },
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println("result=>", prefix)
|
|
|
+ fmt.Println(result.CommonPrefixes, result.IsTruncated)
|
|
|
+ out := []*model.ObsItem{}
|
|
|
+
|
|
|
+ imgExts := map[string]bool{".jpeg": true, ".jpg": true, ".gif": true, ".png": true, ".svg": true, ".bmp": true}
|
|
|
+
|
|
|
+ for k, v := range result.Contents {
|
|
|
+ fmt.Println(k, v.Key, v.LastModified, v.Size)
|
|
|
+ if prefix == v.Key {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ isDirSuffix := strings.HasSuffix(v.Key, "/")
|
|
|
+ isDir := (isDirSuffix && v.Size == 0)
|
|
|
+ isImage := false
|
|
|
+
|
|
|
+ originKey := strings.ToLower(v.Key)
|
|
|
+ if !isDir && imgExts[path.Ext(originKey)] {
|
|
|
+ isImage = true
|
|
|
+ }
|
|
|
+
|
|
|
+ keys := strings.Split(v.Key, "/")
|
|
|
+ name := ""
|
|
|
+ if isDir {
|
|
|
+ name = keys[len(keys)-2]
|
|
|
+ } else {
|
|
|
+ name = keys[len(keys)-1]
|
|
|
+ }
|
|
|
+ obsConf := conf.AppConfig.Obs
|
|
|
+ url := ""
|
|
|
+ if !isDir {
|
|
|
+ url = fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, v.Key)
|
|
|
+ }
|
|
|
+
|
|
|
+ out = append(out, &model.ObsItem{
|
|
|
+ Name: name,
|
|
|
+ Size: uint64(v.Size),
|
|
|
+ IsImage: isImage,
|
|
|
+ Url: url,
|
|
|
+ IsDir: isDir,
|
|
|
+ LastModified: v.LastModified,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range result.CommonPrefixes {
|
|
|
+ keys := strings.Split(v, "/")
|
|
|
+ name := keys[len(keys)-2]
|
|
|
+
|
|
|
+ out = append(out, &model.ObsItem{
|
|
|
+ Name: name,
|
|
|
+ IsImage: false,
|
|
|
+ IsDir: true,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ outMap := map[string]interface{}{
|
|
|
+ "list": out,
|
|
|
+ "isTruncated": result.IsTruncated,
|
|
|
+ }
|
|
|
+ return outMap, nil
|
|
|
+}
|
|
|
+
|
|
|
+// 管理后台上传文件
|
|
|
+func ServiceObsUploadPolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+
|
|
|
+ body := struct {
|
|
|
+ Key string
|
|
|
+ }{}
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("参数解析错误!")
|
|
|
+ }
|
|
|
+ if len(body.Key) < 1 {
|
|
|
+ return nil, NewError("上传文件的key不能为空")
|
|
|
+ }
|
|
|
+ client, err := CreateObsClient()
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("创建ObsClient 失败!")
|
|
|
+ }
|
|
|
+ defer func() {
|
|
|
+ client.Close()
|
|
|
+ }()
|
|
|
+ bucketName := apictx.Svc.Conf.Obs.Bucket
|
|
|
+
|
|
|
+ result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: body.Key,
|
|
|
+ Expires: 600,
|
|
|
+ FormParams: map[string]string{
|
|
|
+ "x-obs-acl": "public-read",
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewLogWithError(err)
|
|
|
+ }
|
|
|
+ obsConf := conf.AppConfig.Obs
|
|
|
+ out := map[string]interface{}{
|
|
|
+ "accessKeyId": obsConf.AccessKeyId,
|
|
|
+ "originPolicy": result.OriginPolicy,
|
|
|
+ "policy": result.Policy,
|
|
|
+ "signature": result.Signature,
|
|
|
+ "host": fmt.Sprintf("https://%s.%s", bucketName, obsConf.Endpoint),
|
|
|
+ "key": body.Key,
|
|
|
+ "saveType": conf.SaveType_Obs,
|
|
|
+ }
|
|
|
+ return out, nil
|
|
|
+}
|
|
|
+
|
|
|
+func ServiceObsRemove(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+
|
|
|
+ body := struct {
|
|
|
+ Key string
|
|
|
+ }{}
|
|
|
+ err := c.ShouldBindJSON(&body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("参数解析错误!")
|
|
|
+ }
|
|
|
+ if len(body.Key) < 1 {
|
|
|
+ return nil, NewError("文件的key不能为空")
|
|
|
+ }
|
|
|
+
|
|
|
+ client, err := CreateObsClient()
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("创建ObsClient 失败!")
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ client.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
+ bucketName := apictx.Svc.Conf.Obs.Bucket
|
|
|
+ result, err := client.DeleteObject(&obs.DeleteObjectInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: body.Key,
|
|
|
+ })
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return result, nil
|
|
|
+}
|
|
|
+
|
|
|
+func ServiceObsCreateFolder(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+ body := struct {
|
|
|
+ Key string
|
|
|
+ }{}
|
|
|
+ err := c.ShouldBindJSON(&body)
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("参数解析错误!")
|
|
|
+ }
|
|
|
+ if len(body.Key) < 1 {
|
|
|
+ return nil, NewError("文件的key不能为空")
|
|
|
+ }
|
|
|
+
|
|
|
+ client, err := CreateObsClient()
|
|
|
+ if err != nil {
|
|
|
+ return nil, NewError("创建ObsClient 失败!")
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ client.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
+ bucketName := apictx.Svc.Conf.Obs.Bucket
|
|
|
+ result, err := client.PutObject(&obs.PutObjectInput{
|
|
|
+ PutObjectBasicInput: obs.PutObjectBasicInput{
|
|
|
+ ObjectOperationInput: obs.ObjectOperationInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: body.Key,
|
|
|
+ ACL: obs.AclPublicRead,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return result, nil
|
|
|
+}
|
|
|
+
|
|
|
+func UploadFile(obsClient *obs.ObsClient, bucketName string, fpath string, obsDir string) *model.OssType {
|
|
|
+
|
|
|
+ _, obsname := path.Split(fpath)
|
|
|
+ keyFormat := "%s/%s"
|
|
|
+ if strings.HasSuffix(obsDir, "/") {
|
|
|
+ keyFormat = "%s%s"
|
|
|
+ }
|
|
|
+ obsKey := fmt.Sprintf(keyFormat, obsDir, obsname)
|
|
|
+
|
|
|
+ input := &obs.PutFileInput{}
|
|
|
+ input.Bucket = bucketName
|
|
|
+ input.Key = obsKey
|
|
|
+ input.SourceFile = fpath
|
|
|
+
|
|
|
+ fpathExt := path.Ext(fpath)
|
|
|
+ isGzFile := fpathExt == ".gz"
|
|
|
+ if isGzFile {
|
|
|
+ input.ContentType = "text/plain"
|
|
|
+ input.Metadata = map[string]string{"Content-Encoding": "gzip"}
|
|
|
+ }
|
|
|
+ result, err := obsClient.PutFile(input)
|
|
|
+
|
|
|
+ isUploadOk := true
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ log.Errorf("upload obs fail %s", fpath)
|
|
|
+ log.Error(err)
|
|
|
+ isUploadOk = false
|
|
|
+ }
|
|
|
+
|
|
|
+ if result.StatusCode != 200 {
|
|
|
+ isUploadOk = false
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isUploadOk {
|
|
|
+ result, err = obsClient.PutFile(input)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ log.Errorf("upload obs fail2 %s", fpath)
|
|
|
+ log.Error(err)
|
|
|
+ return &model.OssType{}
|
|
|
+ }
|
|
|
+ if result.StatusCode != 200 {
|
|
|
+ return &model.OssType{}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if isGzFile {
|
|
|
+ metaRet, err := obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: obsKey,
|
|
|
+ ContentEncoding: "gzip",
|
|
|
+ ContentType: "text/plain",
|
|
|
+ })
|
|
|
+ fmt.Println(metaRet, err)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ metaRet, err = obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
|
|
|
+ Bucket: bucketName,
|
|
|
+ Key: obsKey,
|
|
|
+ ContentEncoding: "gzip",
|
|
|
+ ContentType: "text/plain",
|
|
|
+ })
|
|
|
+ fmt.Println(metaRet, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fi, err := os.Stat(fpath)
|
|
|
+ size := int64(1)
|
|
|
+ if err == nil {
|
|
|
+ size = fi.Size()
|
|
|
+ }
|
|
|
+
|
|
|
+ obsConf := conf.AppConfig.Obs
|
|
|
+
|
|
|
+ return &model.OssType{Url: fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, obsKey), Size: int64(size)}
|
|
|
+}
|