file.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. package v1
  2. import (
  3. "fmt"
  4. "io"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "net/url"
  9. url2 "net/url"
  10. "os"
  11. "path"
  12. "path/filepath"
  13. "strconv"
  14. "strings"
  15. "sync"
  16. "github.com/IceWhaleTech/CasaOS/model"
  17. "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
  18. "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
  19. "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
  20. "github.com/IceWhaleTech/CasaOS/service"
  21. "github.com/gin-gonic/gin"
  22. uuid "github.com/satori/go.uuid"
  23. "go.uber.org/zap"
  24. )
  25. // @Summary 读取文件
  26. // @Produce application/json
  27. // @Accept application/json
  28. // @Tags file
  29. // @Security ApiKeyAuth
  30. // @Param path query string true "路径"
  31. // @Success 200 {string} string "ok"
  32. // @Router /file/read [get]
  33. func GetFilerContent(c *gin.Context) {
  34. filePath := c.Query("path")
  35. if len(filePath) == 0 {
  36. c.JSON(common_err.CLIENT_ERROR, model.Result{
  37. Success: common_err.INVALID_PARAMS,
  38. Message: common_err.GetMsg(common_err.INVALID_PARAMS),
  39. })
  40. return
  41. }
  42. if !file.Exists(filePath) {
  43. c.JSON(common_err.SERVICE_ERROR, model.Result{
  44. Success: common_err.FILE_DOES_NOT_EXIST,
  45. Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
  46. })
  47. return
  48. }
  49. // 文件读取任务是将文件内容读取到内存中。
  50. info, err := ioutil.ReadFile(filePath)
  51. if err != nil {
  52. c.JSON(common_err.SERVICE_ERROR, model.Result{
  53. Success: common_err.FILE_READ_ERROR,
  54. Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
  55. Data: err.Error(),
  56. })
  57. return
  58. }
  59. result := string(info)
  60. c.JSON(common_err.SUCCESS, model.Result{
  61. Success: common_err.SUCCESS,
  62. Message: common_err.GetMsg(common_err.SUCCESS),
  63. Data: result,
  64. })
  65. }
  66. func GetLocalFile(c *gin.Context) {
  67. path := c.Query("path")
  68. if len(path) == 0 {
  69. c.JSON(http.StatusOK, model.Result{
  70. Success: common_err.INVALID_PARAMS,
  71. Message: common_err.GetMsg(common_err.INVALID_PARAMS),
  72. })
  73. return
  74. }
  75. if !file.Exists(path) {
  76. c.JSON(http.StatusOK, model.Result{
  77. Success: common_err.FILE_DOES_NOT_EXIST,
  78. Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
  79. })
  80. return
  81. }
  82. c.File(path)
  83. }
  84. // @Summary download
  85. // @Produce application/json
  86. // @Accept application/json
  87. // @Tags file
  88. // @Security ApiKeyAuth
  89. // @Param format query string false "Compression format" Enums(zip,tar,targz)
  90. // @Param files query string true "file list eg: filename1,filename2,filename3 "
  91. // @Success 200 {string} string "ok"
  92. // @Router /file/download [get]
  93. func GetDownloadFile(c *gin.Context) {
  94. t := c.Query("format")
  95. files := c.Query("files")
  96. if len(files) == 0 {
  97. c.JSON(common_err.CLIENT_ERROR, model.Result{
  98. Success: common_err.INVALID_PARAMS,
  99. Message: common_err.GetMsg(common_err.INVALID_PARAMS),
  100. })
  101. return
  102. }
  103. list := strings.Split(files, ",")
  104. for _, v := range list {
  105. if !file.Exists(v) {
  106. c.JSON(common_err.SERVICE_ERROR, model.Result{
  107. Success: common_err.FILE_DOES_NOT_EXIST,
  108. Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
  109. })
  110. return
  111. }
  112. }
  113. c.Header("Content-Type", "application/octet-stream")
  114. c.Header("Content-Transfer-Encoding", "binary")
  115. c.Header("Cache-Control", "no-cache")
  116. // handles only single files not folders and multiple files
  117. if len(list) == 1 {
  118. filePath := list[0]
  119. info, err := os.Stat(filePath)
  120. if err != nil {
  121. c.JSON(http.StatusOK, model.Result{
  122. Success: common_err.FILE_DOES_NOT_EXIST,
  123. Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
  124. })
  125. return
  126. }
  127. if !info.IsDir() {
  128. // 打开文件
  129. fileTmp, _ := os.Open(filePath)
  130. defer fileTmp.Close()
  131. // 获取文件的名称
  132. fileName := path.Base(filePath)
  133. c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
  134. c.File(filePath)
  135. return
  136. }
  137. }
  138. extension, ar, err := file.GetCompressionAlgorithm(t)
  139. if err != nil {
  140. c.JSON(common_err.CLIENT_ERROR, model.Result{
  141. Success: common_err.INVALID_PARAMS,
  142. Message: common_err.GetMsg(common_err.INVALID_PARAMS),
  143. })
  144. return
  145. }
  146. err = ar.Create(c.Writer)
  147. if err != nil {
  148. c.JSON(common_err.SERVICE_ERROR, model.Result{
  149. Success: common_err.SERVICE_ERROR,
  150. Message: common_err.GetMsg(common_err.SERVICE_ERROR),
  151. Data: err.Error(),
  152. })
  153. return
  154. }
  155. defer ar.Close()
  156. commonDir := file.CommonPrefix(filepath.Separator, list...)
  157. currentPath := filepath.Base(commonDir)
  158. name := "_" + currentPath
  159. name += extension
  160. c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
  161. for _, fname := range list {
  162. err = file.AddFile(ar, fname, commonDir)
  163. if err != nil {
  164. log.Printf("Failed to archive %s: %v", fname, err)
  165. }
  166. }
  167. }
  168. func GetDownloadSingleFile(c *gin.Context) {
  169. filePath := c.Query("path")
  170. if len(filePath) == 0 {
  171. c.JSON(service.ClientCount, model.Result{
  172. Success: common_err.INVALID_PARAMS,
  173. Message: common_err.GetMsg(common_err.INVALID_PARAMS),
  174. })
  175. return
  176. }
  177. fileTmp, err := os.Open(filePath)
  178. if err != nil {
  179. c.JSON(common_err.SERVICE_ERROR, model.Result{
  180. Success: common_err.FILE_DOES_NOT_EXIST,
  181. Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
  182. })
  183. return
  184. }
  185. defer fileTmp.Close()
  186. fileName := path.Base(filePath)
  187. // c.Header("Content-Disposition", "inline")
  188. c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
  189. c.File(filePath)
  190. }
  191. // @Summary 获取目录列表
  192. // @Produce application/json
  193. // @Accept application/json
  194. // @Tags file
  195. // @Security ApiKeyAuth
  196. // @Param path query string false "路径"
  197. // @Success 200 {string} string "ok"
  198. // @Router /file/dirpath [get]
  199. func DirPath(c *gin.Context) {
  200. path := c.DefaultQuery("path", "")
  201. info := service.MyService.System().GetDirPath(path)
  202. shares := service.MyService.Shares().GetSharesList()
  203. sharesMap := make(map[string]string)
  204. for _, v := range shares {
  205. sharesMap[v.Path] = fmt.Sprint(v.ID)
  206. }
  207. if path == "/DATA/AppData" {
  208. list := service.MyService.Docker().DockerContainerList()
  209. apps := make(map[string]string, len(list))
  210. for _, v := range list {
  211. apps[strings.ReplaceAll(v.Names[0], "/", "")] = strings.ReplaceAll(v.Names[0], "/", "")
  212. }
  213. for i := 0; i < len(info); i++ {
  214. if v, ok := apps[info[i].Name]; ok {
  215. info[i].Label = v
  216. info[i].Type = "application"
  217. }
  218. }
  219. }
  220. for i := 0; i < len(info); i++ {
  221. if v, ok := sharesMap[info[i].Path]; ok {
  222. ex := make(map[string]interface{})
  223. shareEx := make(map[string]string)
  224. shareEx["shared"] = "true"
  225. shareEx["id"] = v
  226. ex["share"] = shareEx
  227. info[i].Extensions = ex
  228. }
  229. }
  230. // Hide the files or folders in operation
  231. fileQueue := make(map[string]string)
  232. if len(service.OpStrArr) > 0 {
  233. for _, v := range service.OpStrArr {
  234. v, ok := service.FileQueue.Load(v)
  235. if !ok {
  236. continue
  237. }
  238. vt := v.(model.FileOperate)
  239. for _, i := range vt.Item {
  240. lastPath := i.From[strings.LastIndex(i.From, "/")+1:]
  241. fileQueue[vt.To+"/"+lastPath] = i.From
  242. }
  243. }
  244. }
  245. pathList := []model.Path{}
  246. for i := 0; i < len(info); i++ {
  247. if info[i].Name == ".temp" && info[i].IsDir {
  248. continue
  249. }
  250. if _, ok := fileQueue[info[i].Path]; !ok {
  251. pathList = append(pathList, info[i])
  252. }
  253. }
  254. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: pathList})
  255. }
  256. // @Summary rename file or dir
  257. // @Produce application/json
  258. // @Accept application/json
  259. // @Tags file
  260. // @Security ApiKeyAuth
  261. // @Param oldpath body string true "path of old"
  262. // @Param newpath body string true "path of new"
  263. // @Success 200 {string} string "ok"
  264. // @Router /file/rename [put]
  265. func RenamePath(c *gin.Context) {
  266. json := make(map[string]string)
  267. c.ShouldBind(&json)
  268. op := json["old_path"]
  269. np := json["new_path"]
  270. if len(op) == 0 || len(np) == 0 {
  271. c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  272. return
  273. }
  274. success, err := service.MyService.System().RenameFile(op, np)
  275. c.JSON(common_err.SUCCESS, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
  276. }
  277. // @Summary create folder
  278. // @Produce application/json
  279. // @Accept application/json
  280. // @Tags file
  281. // @Security ApiKeyAuth
  282. // @Param path body string true "path of folder"
  283. // @Success 200 {string} string "ok"
  284. // @Router /file/mkdir [post]
  285. func MkdirAll(c *gin.Context) {
  286. json := make(map[string]string)
  287. c.ShouldBind(&json)
  288. path := json["path"]
  289. var code int
  290. if len(path) == 0 {
  291. c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  292. return
  293. }
  294. // decodedPath, err := url.QueryUnescape(path)
  295. // if err != nil {
  296. // c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  297. // return
  298. // }
  299. code, _ = service.MyService.System().MkdirAll(path)
  300. c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
  301. }
  302. // @Summary create file
  303. // @Produce application/json
  304. // @Accept application/json
  305. // @Tags file
  306. // @Security ApiKeyAuth
  307. // @Param path body string true "path of folder (path need to url encode)"
  308. // @Success 200 {string} string "ok"
  309. // @Router /file/create [post]
  310. func PostCreateFile(c *gin.Context) {
  311. json := make(map[string]string)
  312. c.ShouldBind(&json)
  313. path := json["path"]
  314. var code int
  315. if len(path) == 0 {
  316. c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  317. return
  318. }
  319. // decodedPath, err := url.QueryUnescape(path)
  320. // if err != nil {
  321. // c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  322. // return
  323. // }
  324. code, _ = service.MyService.System().CreateFile(path)
  325. c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
  326. }
  327. // @Summary upload file
  328. // @Produce application/json
  329. // @Accept application/json
  330. // @Tags file
  331. // @Security ApiKeyAuth
  332. // @Param path formData string false "file path"
  333. // @Param file formData file true "file"
  334. // @Success 200 {string} string "ok"
  335. // @Router /file/upload [get]
  336. func GetFileUpload(c *gin.Context) {
  337. relative := c.Query("relativePath")
  338. fileName := c.Query("filename")
  339. chunkNumber := c.Query("chunkNumber")
  340. totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
  341. path := c.Query("path")
  342. dirPath := ""
  343. hash := file.GetHashByContent([]byte(fileName))
  344. tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
  345. if fileName != relative {
  346. dirPath = strings.TrimSuffix(relative, fileName)
  347. tempDir += dirPath
  348. file.MkDir(path + "/" + dirPath)
  349. }
  350. tempDir += chunkNumber
  351. if !file.CheckNotExist(tempDir) {
  352. c.JSON(200, model.Result{Success: 200, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
  353. return
  354. }
  355. c.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)})
  356. }
  357. // @Summary upload file
  358. // @Produce application/json
  359. // @Accept multipart/form-data
  360. // @Tags file
  361. // @Security ApiKeyAuth
  362. // @Param path formData string false "file path"
  363. // @Param file formData file true "file"
  364. // @Success 200 {string} string "ok"
  365. // @Router /file/upload [post]
  366. func PostFileUpload(c *gin.Context) {
  367. f, _, _ := c.Request.FormFile("file")
  368. relative := c.PostForm("relativePath")
  369. fileName := c.PostForm("filename")
  370. totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
  371. chunkNumber := c.PostForm("chunkNumber")
  372. dirPath := ""
  373. path := c.PostForm("path")
  374. hash := file.GetHashByContent([]byte(fileName))
  375. if len(path) == 0 {
  376. loger.Error("path should not be empty")
  377. c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  378. return
  379. }
  380. tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
  381. if fileName != relative {
  382. dirPath = strings.TrimSuffix(relative, fileName)
  383. tempDir += dirPath
  384. if err := file.MkDir(path + "/" + dirPath); err != nil {
  385. loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
  386. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  387. return
  388. }
  389. }
  390. path += "/" + relative
  391. if !file.CheckNotExist(tempDir + chunkNumber) {
  392. if err := file.RMDir(tempDir + chunkNumber); err != nil {
  393. loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
  394. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  395. return
  396. }
  397. }
  398. if totalChunks > 1 {
  399. if err := file.IsNotExistMkDir(tempDir); err != nil {
  400. loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
  401. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  402. return
  403. }
  404. out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
  405. if err != nil {
  406. loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
  407. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  408. return
  409. }
  410. defer out.Close()
  411. if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
  412. loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
  413. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  414. return
  415. }
  416. fileNum, err := ioutil.ReadDir(tempDir)
  417. if err != nil {
  418. loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
  419. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  420. return
  421. }
  422. if totalChunks == len(fileNum) {
  423. if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
  424. loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
  425. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  426. return
  427. }
  428. if err := file.RMDir(tempDir); err != nil {
  429. loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
  430. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  431. return
  432. }
  433. }
  434. } else {
  435. out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
  436. if err != nil {
  437. loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
  438. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
  439. return
  440. }
  441. defer out.Close()
  442. if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
  443. loger.Error("error when trying to write to `"+path+"`", zap.Error(err))
  444. c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
  445. return
  446. }
  447. }
  448. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  449. }
  450. // @Summary copy or move file
  451. // @Produce application/json
  452. // @Accept application/json
  453. // @Tags file
  454. // @Security ApiKeyAuth
  455. // @Param body body model.FileOperate true "type:move,copy"
  456. // @Success 200 {string} string "ok"
  457. // @Router /file/operate [post]
  458. func PostOperateFileOrDir(c *gin.Context) {
  459. list := model.FileOperate{}
  460. c.ShouldBind(&list)
  461. if len(list.Item) == 0 {
  462. c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  463. return
  464. }
  465. if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
  466. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
  467. return
  468. }
  469. var total int64 = 0
  470. for i := 0; i < len(list.Item); i++ {
  471. size, err := file.GetFileOrDirSize(list.Item[i].From)
  472. if err != nil {
  473. continue
  474. }
  475. list.Item[i].Size = size
  476. total += size
  477. }
  478. list.TotalSize = total
  479. list.ProcessedSize = 0
  480. uid := uuid.NewV4().String()
  481. service.FileQueue.Store(uid, list)
  482. service.OpStrArr = append(service.OpStrArr, uid)
  483. if len(service.OpStrArr) == 1 {
  484. go service.ExecOpFile()
  485. go service.CheckFileStatus()
  486. go service.MyService.Notify().SendFileOperateNotify(false)
  487. }
  488. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  489. }
  490. // @Summary delete file
  491. // @Produce application/json
  492. // @Accept application/json
  493. // @Tags file
  494. // @Security ApiKeyAuth
  495. // @Param body body string true "paths eg ["/a/b/c","/d/e/f"]"
  496. // @Success 200 {string} string "ok"
  497. // @Router /file/delete [delete]
  498. func DeleteFile(c *gin.Context) {
  499. paths := []string{}
  500. c.ShouldBind(&paths)
  501. if len(paths) == 0 {
  502. c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
  503. return
  504. }
  505. // path := c.Query("path")
  506. // paths := strings.Split(path, ",")
  507. for _, v := range paths {
  508. err := os.RemoveAll(v)
  509. if err != nil {
  510. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
  511. return
  512. }
  513. }
  514. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  515. }
  516. // @Summary update file
  517. // @Produce application/json
  518. // @Accept application/json
  519. // @Tags file
  520. // @Security ApiKeyAuth
  521. // @Param path body string true "path"
  522. // @Param content body string true "content"
  523. // @Success 200 {string} string "ok"
  524. // @Router /file/update [put]
  525. func PutFileContent(c *gin.Context) {
  526. fi := model.FileUpdate{}
  527. c.ShouldBind(&fi)
  528. // path := c.PostForm("path")
  529. // content := c.PostForm("content")
  530. if !file.Exists(fi.FilePath) {
  531. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
  532. return
  533. }
  534. // err := os.Remove(path)
  535. err := os.RemoveAll(fi.FilePath)
  536. if err != nil {
  537. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
  538. return
  539. }
  540. err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
  541. if err != nil {
  542. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
  543. return
  544. }
  545. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  546. }
  547. // @Summary image thumbnail/original image
  548. // @Produce application/json
  549. // @Accept application/json
  550. // @Tags file
  551. // @Security ApiKeyAuth
  552. // @Param path query string true "path"
  553. // @Param type query string false "original,thumbnail" Enums(original,thumbnail)
  554. // @Success 200 {string} string "ok"
  555. // @Router /file/image [get]
  556. func GetFileImage(c *gin.Context) {
  557. t := c.Query("type")
  558. path := c.Query("path")
  559. if !file.Exists(path) {
  560. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
  561. return
  562. }
  563. if t == "thumbnail" {
  564. f, err := file.GetImage(path, 100, 0)
  565. if err != nil {
  566. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
  567. return
  568. }
  569. c.Writer.WriteString(string(f))
  570. return
  571. }
  572. f, err := os.Open(path)
  573. if err != nil {
  574. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
  575. return
  576. }
  577. defer f.Close()
  578. data, err := ioutil.ReadAll(f)
  579. if err != nil {
  580. c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
  581. return
  582. }
  583. c.Writer.WriteString(string(data))
  584. }
  585. func DeleteOperateFileOrDir(c *gin.Context) {
  586. id := c.Param("id")
  587. if id == "0" {
  588. service.FileQueue = sync.Map{}
  589. service.OpStrArr = []string{}
  590. } else {
  591. service.FileQueue.Delete(id)
  592. tempList := []string{}
  593. for _, v := range service.OpStrArr {
  594. if v != id {
  595. tempList = append(tempList, v)
  596. }
  597. }
  598. service.OpStrArr = tempList
  599. }
  600. go service.MyService.Notify().SendFileOperateNotify(true)
  601. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  602. }