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.

uploadhandler.go 3.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. Copyright (c) [2023] [pcm]
  3. [pcm-coordinator] is licensed under Mulan PSL v2.
  4. You can use this software according to the terms and conditions of the Mulan PSL v2.
  5. You may obtain a copy of Mulan PSL v2 at:
  6. http://license.coscl.org.cn/MulanPSL2
  7. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
  8. EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
  9. MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  10. See the Mulan PSL v2 for more details.
  11. */
  12. package image
  13. import (
  14. "bufio"
  15. "fmt"
  16. "github.com/zeromicro/go-zero/core/logx"
  17. "gitlink.org.cn/jcce-pcm/pcm-coordinator/api/internal/svc"
  18. "gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/repository/result"
  19. "gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/utils/fileutils"
  20. "io"
  21. "net/http"
  22. "os"
  23. "path/filepath"
  24. "strconv"
  25. "syscall"
  26. )
  27. type LoadBody struct {
  28. Stream string `json:"stream"`
  29. }
  30. var uploadTempPath = filepath.Join(uploadPath, "temp")
  31. func UploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  32. return func(w http.ResponseWriter, r *http.Request) {
  33. file, fileHeader, err := r.FormFile("file")
  34. if err != nil {
  35. logx.Error(err)
  36. result.HttpResult(r, w, nil, err)
  37. return
  38. }
  39. index := r.PostFormValue("index")
  40. hash := r.PostFormValue("hash")
  41. defer file.Close()
  42. // 合并路径
  43. chunksPath := filepath.Join(uploadTempPath, hash)
  44. // 文件路径
  45. filePath := filepath.Join(chunksPath, hash+"-"+index)
  46. // 检查临时文件夹是否存在 不存在则创建文件夹
  47. isPathExists, err := fileutils.PathExists(chunksPath)
  48. if !isPathExists {
  49. err = os.MkdirAll(chunksPath, os.ModePerm)
  50. if err != nil {
  51. logx.Error(err)
  52. result.HttpResult(r, w, nil, err)
  53. return
  54. }
  55. }
  56. // 检查文件是否存在
  57. exists, err := fileutils.PathExists(filePath)
  58. if err != nil {
  59. logx.Error(err)
  60. result.HttpResult(r, w, nil, err)
  61. return
  62. }
  63. // 文件存在 进行断点续传
  64. if exists {
  65. fileInfo, _ := os.Stat(filePath)
  66. if fileInfo.Size() == fileHeader.Size {
  67. result.HttpResult(r, w, nil, err)
  68. return
  69. }
  70. start := strconv.Itoa(int(fileInfo.Size()))
  71. oldFile, _ := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, os.ModePerm)
  72. defer oldFile.Close()
  73. count, _ := strconv.ParseInt(start, 10, 64)
  74. fmt.Println("已上传:", count)
  75. // 设置读,写的偏移量
  76. file.Seek(count, 0)
  77. oldFile.Seek(count, 0)
  78. data := make([]byte, 1024, 1024)
  79. for {
  80. total, err := file.Read(data)
  81. if err == io.EOF {
  82. fmt.Println("文件复制完毕")
  83. break
  84. }
  85. oldFile.Write(data[:total])
  86. }
  87. // 文件不存在 直接上传
  88. } else {
  89. destFile, _ := os.OpenFile(filepath.Join(chunksPath, hash+"-"+index), syscall.O_CREAT|syscall.O_WRONLY, 0777)
  90. reader := bufio.NewReader(file)
  91. writer := bufio.NewWriter(destFile)
  92. buf := make([]byte, 1024*1024) // 1M buf
  93. for {
  94. n, err := reader.Read(buf)
  95. if err == io.EOF {
  96. writer.Flush()
  97. break
  98. } else if err != nil {
  99. return
  100. } else {
  101. writer.Write(buf[:n])
  102. }
  103. }
  104. defer file.Close()
  105. defer destFile.Close()
  106. }
  107. result.HttpResult(r, w, nil, err)
  108. }
  109. }

PCM is positioned as Software stack over Cloud, aiming to build the standards and ecology of heterogeneous cloud collaboration for JCC in a non intrusive and autonomous peer-to-peer manner.