You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

object.go 13 kB

1 year ago
11 months ago
11 months ago
1 year ago
11 months ago
11 months ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. package cdsapi
  2. import (
  3. "fmt"
  4. "io"
  5. "mime"
  6. "net/url"
  7. "strings"
  8. "time"
  9. "gitlink.org.cn/cloudream/common/consts/errorcode"
  10. "gitlink.org.cn/cloudream/common/pkgs/iterator"
  11. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  12. "gitlink.org.cn/cloudream/common/utils/http2"
  13. "gitlink.org.cn/cloudream/common/utils/serder"
  14. )
  15. type ObjectService struct {
  16. *Client
  17. }
  18. func (c *Client) Object() *ObjectService {
  19. return &ObjectService{
  20. Client: c,
  21. }
  22. }
  23. const ObjectListPath = "/object/list"
  24. type ObjectList struct {
  25. UserID cdssdk.UserID `form:"userID" binding:"required"`
  26. PackageID cdssdk.PackageID `form:"packageID" binding:"required"`
  27. Path string `form:"path"` // 允许为空字符串
  28. IsPrefix bool `form:"isPrefix"`
  29. }
  30. type ObjectListResp struct {
  31. Objects []cdssdk.Object `json:"objects"`
  32. }
  33. func (c *ObjectService) List(req ObjectList) (*ObjectListResp, error) {
  34. url, err := url.JoinPath(c.baseURL, ObjectListPath)
  35. if err != nil {
  36. return nil, err
  37. }
  38. resp, err := http2.GetForm(url, http2.RequestParam{
  39. Query: req,
  40. })
  41. if err != nil {
  42. return nil, err
  43. }
  44. jsonResp, err := ParseJSONResponse[response[ObjectListResp]](resp)
  45. if err != nil {
  46. return nil, err
  47. }
  48. if jsonResp.Code == errorcode.OK {
  49. return &jsonResp.Data, nil
  50. }
  51. return nil, jsonResp.ToError()
  52. }
  53. const ObjectListByIDsPath = "/object/listByIDs"
  54. type ObjectListByIDs struct {
  55. UserID cdssdk.UserID `json:"userID" binding:"required"`
  56. ObjectIDs []cdssdk.ObjectID `json:"objectIDs" binding:"required"`
  57. }
  58. type ObjectListByIDsResp struct {
  59. Objects []*cdssdk.Object `json:"object"` // 与ObjectIDs一一对应,如果某个ID不存在,则对应位置为nil
  60. }
  61. func (c *ObjectService) ListByIDs(req ObjectListByIDs) (*ObjectListByIDsResp, error) {
  62. url, err := url.JoinPath(c.baseURL, ObjectListByIDsPath)
  63. if err != nil {
  64. return nil, err
  65. }
  66. resp, err := http2.PostJSON(url, http2.RequestParam{
  67. Body: req,
  68. })
  69. if err != nil {
  70. return nil, err
  71. }
  72. jsonResp, err := ParseJSONResponse[response[ObjectListByIDsResp]](resp)
  73. if err != nil {
  74. return nil, err
  75. }
  76. if jsonResp.Code == errorcode.OK {
  77. return &jsonResp.Data, nil
  78. }
  79. return nil, jsonResp.ToError()
  80. }
  81. const ObjectUploadPath = "/object/upload"
  82. type ObjectUpload struct {
  83. ObjectUploadInfo
  84. Files UploadObjectIterator `json:"-"`
  85. }
  86. type ObjectUploadInfo struct {
  87. UserID cdssdk.UserID `json:"userID" binding:"required"`
  88. PackageID cdssdk.PackageID `json:"packageID" binding:"required"`
  89. Affinity cdssdk.StorageID `json:"affinity"`
  90. LoadTo []cdssdk.StorageID `json:"loadTo"`
  91. LoadToPath []string `json:"loadToPath"`
  92. }
  93. type UploadingObject struct {
  94. Path string
  95. File io.ReadCloser
  96. }
  97. type UploadObjectIterator = iterator.Iterator[*UploadingObject]
  98. type ObjectUploadResp struct {
  99. Uploadeds []cdssdk.Object `json:"uploadeds"`
  100. }
  101. func (c *ObjectService) Upload(req ObjectUpload) (*ObjectUploadResp, error) {
  102. url, err := url.JoinPath(c.baseURL, ObjectUploadPath)
  103. if err != nil {
  104. return nil, err
  105. }
  106. infoJSON, err := serder.ObjectToJSON(req)
  107. if err != nil {
  108. return nil, fmt.Errorf("upload info to json: %w", err)
  109. }
  110. resp, err := http2.PostMultiPart(url, http2.MultiPartRequestParam{
  111. Form: map[string]string{"info": string(infoJSON)},
  112. Files: iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) {
  113. return &http2.IterMultiPartFile{
  114. FieldName: "files",
  115. FileName: src.Path,
  116. File: src.File,
  117. }, nil
  118. }),
  119. })
  120. if err != nil {
  121. return nil, err
  122. }
  123. contType := resp.Header.Get("Content-Type")
  124. if strings.Contains(contType, http2.ContentTypeJSON) {
  125. var err error
  126. var codeResp response[ObjectUploadResp]
  127. if codeResp, err = serder.JSONToObjectStreamEx[response[ObjectUploadResp]](resp.Body); err != nil {
  128. return nil, fmt.Errorf("parsing response: %w", err)
  129. }
  130. if codeResp.Code == errorcode.OK {
  131. return &codeResp.Data, nil
  132. }
  133. return nil, codeResp.ToError()
  134. }
  135. return nil, fmt.Errorf("unknow response content type: %s", contType)
  136. }
  137. const ObjectDownloadPath = "/object/download"
  138. type ObjectDownload struct {
  139. UserID cdssdk.UserID `form:"userID" json:"userID" binding:"required"`
  140. ObjectID cdssdk.ObjectID `form:"objectID" json:"objectID" binding:"required"`
  141. Offset int64 `form:"offset" json:"offset,omitempty"`
  142. Length *int64 `form:"length" json:"length,omitempty"`
  143. }
  144. type DownloadingObject struct {
  145. Path string
  146. File io.ReadCloser
  147. }
  148. func (c *ObjectService) Download(req ObjectDownload) (*DownloadingObject, error) {
  149. url, err := url.JoinPath(c.baseURL, ObjectDownloadPath)
  150. if err != nil {
  151. return nil, err
  152. }
  153. resp, err := http2.GetJSON(url, http2.RequestParam{
  154. Query: req,
  155. })
  156. if err != nil {
  157. return nil, err
  158. }
  159. contType := resp.Header.Get("Content-Type")
  160. if strings.Contains(contType, http2.ContentTypeJSON) {
  161. var codeResp response[any]
  162. if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
  163. return nil, fmt.Errorf("parsing response: %w", err)
  164. }
  165. return nil, codeResp.ToError()
  166. }
  167. _, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition"))
  168. if err != nil {
  169. return nil, fmt.Errorf("parsing content disposition: %w", err)
  170. }
  171. return &DownloadingObject{
  172. Path: params["filename"],
  173. File: resp.Body,
  174. }, nil
  175. }
  176. const ObjectDownloadByPathPath = "/object/downloadByPath"
  177. type ObjectDownloadByPath struct {
  178. UserID cdssdk.UserID `form:"userID" json:"userID" binding:"required"`
  179. PackageID cdssdk.PackageID `form:"packageID" json:"packageID" binding:"required"`
  180. Path string `form:"path" json:"path" binding:"required"`
  181. Offset int64 `form:"offset" json:"offset,omitempty"`
  182. Length *int64 `form:"length" json:"length,omitempty"`
  183. }
  184. func (c *ObjectService) DownloadByPath(req ObjectDownloadByPath) (*DownloadingObject, error) {
  185. url, err := url.JoinPath(c.baseURL, ObjectDownloadByPathPath)
  186. if err != nil {
  187. return nil, err
  188. }
  189. resp, err := http2.GetJSON(url, http2.RequestParam{
  190. Query: req,
  191. })
  192. if err != nil {
  193. return nil, err
  194. }
  195. contType := resp.Header.Get("Content-Type")
  196. if strings.Contains(contType, http2.ContentTypeJSON) {
  197. var codeResp response[any]
  198. if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
  199. return nil, fmt.Errorf("parsing response: %w", err)
  200. }
  201. return nil, codeResp.ToError()
  202. }
  203. _, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition"))
  204. if err != nil {
  205. return nil, fmt.Errorf("parsing content disposition: %w", err)
  206. }
  207. return &DownloadingObject{
  208. Path: params["filename"],
  209. File: resp.Body,
  210. }, nil
  211. }
  212. const ObjectUpdateInfoPath = "/object/updateInfo"
  213. type UpdatingObject struct {
  214. ObjectID cdssdk.ObjectID `json:"objectID" binding:"required"`
  215. UpdateTime time.Time `json:"updateTime" binding:"required"`
  216. }
  217. func (u *UpdatingObject) ApplyTo(obj *cdssdk.Object) {
  218. obj.UpdateTime = u.UpdateTime
  219. }
  220. type ObjectUpdateInfo struct {
  221. UserID cdssdk.UserID `json:"userID" binding:"required"`
  222. Updatings []UpdatingObject `json:"updatings" binding:"required"`
  223. }
  224. type ObjectUpdateInfoResp struct {
  225. Successes []cdssdk.ObjectID `json:"successes"`
  226. }
  227. func (c *ObjectService) UpdateInfo(req ObjectUpdateInfo) (*ObjectUpdateInfoResp, error) {
  228. url, err := url.JoinPath(c.baseURL, ObjectUpdateInfoPath)
  229. if err != nil {
  230. return nil, err
  231. }
  232. resp, err := http2.PostJSON(url, http2.RequestParam{
  233. Body: req,
  234. })
  235. if err != nil {
  236. return nil, err
  237. }
  238. jsonResp, err := ParseJSONResponse[response[ObjectUpdateInfoResp]](resp)
  239. if err != nil {
  240. return nil, err
  241. }
  242. if jsonResp.Code == errorcode.OK {
  243. return &jsonResp.Data, nil
  244. }
  245. return nil, jsonResp.ToError()
  246. }
  247. const ObjectUpdateInfoByPathPath = "/object/updateInfoByPath"
  248. type ObjectUpdateInfoByPath struct {
  249. UserID cdssdk.UserID `json:"userID" binding:"required"`
  250. PackageID cdssdk.PackageID `json:"packageID" binding:"required"`
  251. Path string `json:"path" binding:"required"`
  252. UpdateTime time.Time `json:"updateTime" binding:"required"`
  253. }
  254. type ObjectUpdateInfoByPathResp struct{}
  255. func (c *ObjectService) UpdateInfoByPath(req ObjectUpdateInfoByPath) (*ObjectUpdateInfoByPathResp, error) {
  256. url, err := url.JoinPath(c.baseURL, ObjectUpdateInfoByPathPath)
  257. if err != nil {
  258. return nil, err
  259. }
  260. resp, err := http2.PostJSON(url, http2.RequestParam{
  261. Body: req,
  262. })
  263. if err != nil {
  264. return nil, err
  265. }
  266. jsonResp, err := ParseJSONResponse[response[ObjectUpdateInfoByPathResp]](resp)
  267. if err != nil {
  268. return nil, err
  269. }
  270. if jsonResp.Code == errorcode.OK {
  271. return &jsonResp.Data, nil
  272. }
  273. return nil, jsonResp.ToError()
  274. }
  275. const ObjectMovePath = "/object/move"
  276. type MovingObject struct {
  277. ObjectID cdssdk.ObjectID `json:"objectID" binding:"required"`
  278. PackageID cdssdk.PackageID `json:"packageID" binding:"required"`
  279. Path string `json:"path" binding:"required"`
  280. }
  281. func (m *MovingObject) ApplyTo(obj *cdssdk.Object) {
  282. obj.PackageID = m.PackageID
  283. obj.Path = m.Path
  284. }
  285. type ObjectMove struct {
  286. UserID cdssdk.UserID `json:"userID" binding:"required"`
  287. Movings []MovingObject `json:"movings" binding:"required"`
  288. }
  289. type ObjectMoveResp struct {
  290. Successes []cdssdk.ObjectID `json:"successes"`
  291. }
  292. func (c *ObjectService) Move(req ObjectMove) (*ObjectMoveResp, error) {
  293. url, err := url.JoinPath(c.baseURL, ObjectMovePath)
  294. if err != nil {
  295. return nil, err
  296. }
  297. resp, err := http2.PostJSON(url, http2.RequestParam{
  298. Body: req,
  299. })
  300. if err != nil {
  301. return nil, err
  302. }
  303. jsonResp, err := ParseJSONResponse[response[ObjectMoveResp]](resp)
  304. if err != nil {
  305. return nil, err
  306. }
  307. if jsonResp.Code == errorcode.OK {
  308. return &jsonResp.Data, nil
  309. }
  310. return nil, jsonResp.ToError()
  311. }
  312. const ObjectDeletePath = "/object/delete"
  313. type ObjectDelete struct {
  314. UserID cdssdk.UserID `json:"userID" binding:"required"`
  315. ObjectIDs []cdssdk.ObjectID `json:"objectIDs" binding:"required"`
  316. }
  317. type ObjectDeleteResp struct{}
  318. func (c *ObjectService) Delete(req ObjectDelete) error {
  319. url, err := url.JoinPath(c.baseURL, ObjectDeletePath)
  320. if err != nil {
  321. return err
  322. }
  323. resp, err := http2.PostJSON(url, http2.RequestParam{
  324. Body: req,
  325. })
  326. if err != nil {
  327. return err
  328. }
  329. jsonResp, err := ParseJSONResponse[response[ObjectDeleteResp]](resp)
  330. if err != nil {
  331. return err
  332. }
  333. if jsonResp.Code == errorcode.OK {
  334. return nil
  335. }
  336. return jsonResp.ToError()
  337. }
  338. const ObjectDeleteByPathPath = "/object/deleteByPath"
  339. type ObjectDeleteByPath struct {
  340. UserID cdssdk.UserID `json:"userID" binding:"required"`
  341. PackageID cdssdk.PackageID `json:"packageID" binding:"required"`
  342. Path string `json:"path" binding:"required"`
  343. }
  344. type ObjectDeleteByPathResp struct{}
  345. func (c *ObjectService) DeleteByPath(req ObjectDeleteByPath) error {
  346. url, err := url.JoinPath(c.baseURL, ObjectDeleteByPathPath)
  347. if err != nil {
  348. return err
  349. }
  350. resp, err := http2.PostJSON(url, http2.RequestParam{
  351. Body: req,
  352. })
  353. if err != nil {
  354. return err
  355. }
  356. jsonResp, err := ParseJSONResponse[response[ObjectDeleteByPathResp]](resp)
  357. if err != nil {
  358. return err
  359. }
  360. if jsonResp.Code == errorcode.OK {
  361. return nil
  362. }
  363. return jsonResp.ToError()
  364. }
  365. const ObjectClonePath = "/object/clone"
  366. type ObjectClone struct {
  367. UserID cdssdk.UserID `json:"userID" binding:"required"`
  368. Clonings []CloningObject `json:"clonings" binding:"required"`
  369. }
  370. type CloningObject struct {
  371. ObjectID cdssdk.ObjectID `json:"objectID" binding:"required"`
  372. NewPath string `json:"newPath" binding:"required"`
  373. NewPackageID cdssdk.PackageID `json:"newPackageID" binding:"required"`
  374. }
  375. type ObjectCloneResp struct {
  376. Objects []*cdssdk.Object `json:"objects"`
  377. }
  378. func (c *ObjectService) Clone(req ObjectClone) (*ObjectCloneResp, error) {
  379. url, err := url.JoinPath(c.baseURL, ObjectClonePath)
  380. if err != nil {
  381. return nil, err
  382. }
  383. resp, err := http2.PostJSON(url, http2.RequestParam{
  384. Body: req,
  385. })
  386. if err != nil {
  387. return nil, err
  388. }
  389. jsonResp, err := ParseJSONResponse[response[ObjectCloneResp]](resp)
  390. if err != nil {
  391. return nil, err
  392. }
  393. if jsonResp.Code == errorcode.OK {
  394. return &jsonResp.Data, nil
  395. }
  396. return nil, jsonResp.ToError()
  397. }
  398. const ObjectGetPackageObjectsPath = "/object/getPackageObjects"
  399. type ObjectGetPackageObjects struct {
  400. UserID cdssdk.UserID `form:"userID" json:"userID" binding:"required"`
  401. PackageID cdssdk.PackageID `form:"packageID" json:"packageID" binding:"required"`
  402. }
  403. type ObjectGetPackageObjectsResp struct {
  404. Objects []cdssdk.Object `json:"objects"`
  405. }
  406. func (c *ObjectService) GetPackageObjects(req ObjectGetPackageObjects) (*ObjectGetPackageObjectsResp, error) {
  407. url, err := url.JoinPath(c.baseURL, ObjectGetPackageObjectsPath)
  408. if err != nil {
  409. return nil, err
  410. }
  411. resp, err := http2.GetForm(url, http2.RequestParam{
  412. Query: req,
  413. })
  414. if err != nil {
  415. return nil, err
  416. }
  417. jsonResp, err := ParseJSONResponse[response[ObjectGetPackageObjectsResp]](resp)
  418. if err != nil {
  419. return nil, err
  420. }
  421. if jsonResp.Code == errorcode.OK {
  422. return &jsonResp.Data, nil
  423. }
  424. return nil, jsonResp.ToError()
  425. }