obs.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. package api
  2. import (
  3. "box-cost/conf"
  4. "box-cost/db/model"
  5. "box-cost/log"
  6. "fmt"
  7. "os"
  8. "path"
  9. "strings"
  10. "time"
  11. "github.com/gin-gonic/gin"
  12. "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
  13. )
  14. func CreateObsClient() (*obs.ObsClient, error) {
  15. obsConf := conf.AppConfig.Obs
  16. return obs.New(obsConf.AccessKeyId, obsConf.SecrateKey, obsConf.Endpoint)
  17. }
  18. // u/xxx/img/up/timps.png
  19. func ServiceObsCreateImagePolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  20. body := struct {
  21. Ext string
  22. }{}
  23. err := c.ShouldBindJSON(&body)
  24. if err != nil {
  25. return nil, NewError("参数解析错误!")
  26. }
  27. if len(body.Ext) < 1 {
  28. return nil, NewError("上传文件的扩展名不能为空")
  29. }
  30. fkey := fmt.Sprintf("u/%s/images/uploads/%v.%s", apictx.User.Parent, time.Now().UnixNano(), body.Ext)
  31. client, err := CreateObsClient()
  32. if err != nil {
  33. return nil, NewError("创建ObsClient 失败!")
  34. }
  35. defer func() {
  36. client.Close()
  37. }()
  38. // 除key,policy,signature外,表单上传时的其他参数,支持的值:
  39. // acl
  40. // cache-control
  41. // content-type
  42. // content-disposition
  43. // content-encoding
  44. // expires
  45. bucketName := apictx.Svc.Conf.Obs.Bucket
  46. result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
  47. Bucket: bucketName,
  48. Key: fkey,
  49. Expires: 300,
  50. FormParams: map[string]string{
  51. "x-obs-acl": "public-read",
  52. },
  53. })
  54. if err != nil {
  55. return nil, NewLogWithError(err)
  56. }
  57. obsConf := conf.AppConfig.Obs
  58. out := map[string]interface{}{
  59. "accessKeyId": obsConf.AccessKeyId,
  60. "originPolicy": result.OriginPolicy,
  61. "policy": result.Policy,
  62. "signature": result.Signature,
  63. "host": fmt.Sprintf("//%s.%s", bucketName, obsConf.Endpoint),
  64. "key": fkey,
  65. }
  66. return out, nil
  67. }
  68. func ServiceObsList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  69. prefix := c.Query("prefix")
  70. if len(prefix) < 1 {
  71. return nil, NewError("prefix不能为空")
  72. }
  73. client, err := CreateObsClient()
  74. if err != nil {
  75. return nil, NewError("创建ObsClient 失败!")
  76. }
  77. defer func() {
  78. client.Close()
  79. }()
  80. bucketName := apictx.Svc.Conf.Obs.Bucket
  81. result, err := client.ListObjects(&obs.ListObjectsInput{
  82. Bucket: bucketName,
  83. ListObjsInput: obs.ListObjsInput{
  84. Prefix: prefix,
  85. Delimiter: "/",
  86. },
  87. })
  88. if err != nil {
  89. return nil, err
  90. }
  91. fmt.Println("result=>", prefix)
  92. fmt.Println(result.CommonPrefixes, result.IsTruncated)
  93. out := []*model.ObsItem{}
  94. imgExts := map[string]bool{".jpeg": true, ".jpg": true, ".gif": true, ".png": true, ".svg": true, ".bmp": true}
  95. for k, v := range result.Contents {
  96. fmt.Println(k, v.Key, v.LastModified, v.Size)
  97. if prefix == v.Key {
  98. continue
  99. }
  100. isDirSuffix := strings.HasSuffix(v.Key, "/")
  101. isDir := (isDirSuffix && v.Size == 0)
  102. isImage := false
  103. originKey := strings.ToLower(v.Key)
  104. if !isDir && imgExts[path.Ext(originKey)] {
  105. isImage = true
  106. }
  107. keys := strings.Split(v.Key, "/")
  108. name := ""
  109. if isDir {
  110. name = keys[len(keys)-2]
  111. } else {
  112. name = keys[len(keys)-1]
  113. }
  114. obsConf := conf.AppConfig.Obs
  115. url := ""
  116. if !isDir {
  117. url = fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, v.Key)
  118. }
  119. out = append(out, &model.ObsItem{
  120. Name: name,
  121. Size: uint64(v.Size),
  122. IsImage: isImage,
  123. Url: url,
  124. IsDir: isDir,
  125. LastModified: v.LastModified,
  126. })
  127. }
  128. for _, v := range result.CommonPrefixes {
  129. keys := strings.Split(v, "/")
  130. name := keys[len(keys)-2]
  131. out = append(out, &model.ObsItem{
  132. Name: name,
  133. IsImage: false,
  134. IsDir: true,
  135. })
  136. }
  137. outMap := map[string]interface{}{
  138. "list": out,
  139. "isTruncated": result.IsTruncated,
  140. }
  141. return outMap, nil
  142. }
  143. // 管理后台上传文件
  144. func ServiceObsUploadPolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  145. body := struct {
  146. Key string
  147. }{}
  148. err := c.ShouldBindJSON(&body)
  149. if err != nil {
  150. return nil, NewError("参数解析错误!")
  151. }
  152. if len(body.Key) < 1 {
  153. return nil, NewError("上传文件的key不能为空")
  154. }
  155. client, err := CreateObsClient()
  156. if err != nil {
  157. return nil, NewError("创建ObsClient 失败!")
  158. }
  159. defer func() {
  160. client.Close()
  161. }()
  162. bucketName := apictx.Svc.Conf.Obs.Bucket
  163. result, err := client.CreateBrowserBasedSignature(&obs.CreateBrowserBasedSignatureInput{
  164. Bucket: bucketName,
  165. Key: body.Key,
  166. Expires: 600,
  167. FormParams: map[string]string{
  168. "x-obs-acl": "public-read",
  169. },
  170. })
  171. if err != nil {
  172. return nil, NewLogWithError(err)
  173. }
  174. obsConf := conf.AppConfig.Obs
  175. out := map[string]interface{}{
  176. "accessKeyId": obsConf.AccessKeyId,
  177. "originPolicy": result.OriginPolicy,
  178. "policy": result.Policy,
  179. "signature": result.Signature,
  180. "host": fmt.Sprintf("https://%s.%s", bucketName, obsConf.Endpoint),
  181. "key": body.Key,
  182. "saveType": conf.SaveType_Obs,
  183. }
  184. return out, nil
  185. }
  186. func ServiceObsRemove(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  187. body := struct {
  188. Key string
  189. }{}
  190. err := c.ShouldBindJSON(&body)
  191. if err != nil {
  192. return nil, NewError("参数解析错误!")
  193. }
  194. if len(body.Key) < 1 {
  195. return nil, NewError("文件的key不能为空")
  196. }
  197. client, err := CreateObsClient()
  198. if err != nil {
  199. return nil, NewError("创建ObsClient 失败!")
  200. }
  201. defer func() {
  202. client.Close()
  203. }()
  204. bucketName := apictx.Svc.Conf.Obs.Bucket
  205. result, err := client.DeleteObject(&obs.DeleteObjectInput{
  206. Bucket: bucketName,
  207. Key: body.Key,
  208. })
  209. if err != nil {
  210. return nil, err
  211. }
  212. return result, nil
  213. }
  214. func ServiceObsCreateFolder(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  215. body := struct {
  216. Key string
  217. }{}
  218. err := c.ShouldBindJSON(&body)
  219. if err != nil {
  220. return nil, NewError("参数解析错误!")
  221. }
  222. if len(body.Key) < 1 {
  223. return nil, NewError("文件的key不能为空")
  224. }
  225. client, err := CreateObsClient()
  226. if err != nil {
  227. return nil, NewError("创建ObsClient 失败!")
  228. }
  229. defer func() {
  230. client.Close()
  231. }()
  232. bucketName := apictx.Svc.Conf.Obs.Bucket
  233. result, err := client.PutObject(&obs.PutObjectInput{
  234. PutObjectBasicInput: obs.PutObjectBasicInput{
  235. ObjectOperationInput: obs.ObjectOperationInput{
  236. Bucket: bucketName,
  237. Key: body.Key,
  238. ACL: obs.AclPublicRead,
  239. },
  240. },
  241. })
  242. if err != nil {
  243. return nil, err
  244. }
  245. return result, nil
  246. }
  247. func UploadFile(obsClient *obs.ObsClient, bucketName string, fpath string, obsDir string) *model.OssType {
  248. _, obsname := path.Split(fpath)
  249. keyFormat := "%s/%s"
  250. if strings.HasSuffix(obsDir, "/") {
  251. keyFormat = "%s%s"
  252. }
  253. obsKey := fmt.Sprintf(keyFormat, obsDir, obsname)
  254. input := &obs.PutFileInput{}
  255. input.Bucket = bucketName
  256. input.Key = obsKey
  257. input.SourceFile = fpath
  258. fpathExt := path.Ext(fpath)
  259. isGzFile := fpathExt == ".gz"
  260. if isGzFile {
  261. input.ContentType = "text/plain"
  262. input.Metadata = map[string]string{"Content-Encoding": "gzip"}
  263. }
  264. result, err := obsClient.PutFile(input)
  265. isUploadOk := true
  266. if err != nil {
  267. log.Errorf("upload obs fail %s", fpath)
  268. log.Error(err)
  269. isUploadOk = false
  270. }
  271. if result.StatusCode != 200 {
  272. isUploadOk = false
  273. }
  274. if !isUploadOk {
  275. result, err = obsClient.PutFile(input)
  276. if err != nil {
  277. log.Errorf("upload obs fail2 %s", fpath)
  278. log.Error(err)
  279. return &model.OssType{}
  280. }
  281. if result.StatusCode != 200 {
  282. return &model.OssType{}
  283. }
  284. }
  285. if isGzFile {
  286. metaRet, err := obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
  287. Bucket: bucketName,
  288. Key: obsKey,
  289. ContentEncoding: "gzip",
  290. ContentType: "text/plain",
  291. })
  292. fmt.Println(metaRet, err)
  293. if err != nil {
  294. metaRet, err = obsClient.SetObjectMetadata(&obs.SetObjectMetadataInput{
  295. Bucket: bucketName,
  296. Key: obsKey,
  297. ContentEncoding: "gzip",
  298. ContentType: "text/plain",
  299. })
  300. fmt.Println(metaRet, err)
  301. }
  302. }
  303. fi, err := os.Stat(fpath)
  304. size := int64(1)
  305. if err == nil {
  306. size = fi.Size()
  307. }
  308. obsConf := conf.AppConfig.Obs
  309. return &model.OssType{Url: fmt.Sprintf("//%s.%s/%s", bucketName, obsConf.Endpoint, obsKey), Size: int64(size)}
  310. }