test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "mime/multipart"
  7. "net/http"
  8. "os"
  9. )
  10. func main() {
  11. filePath := "C:\\Users\\lx\\Downloads\\ubuntu-22.04.4-live-server-amd64.iso"
  12. chunkSize := int64(1024 * 1024 * 100) // 100MB 分块大小
  13. fileID := "unique-file-id" // 文件唯一标识符
  14. // 打开文件
  15. file, err := os.Open(filePath)
  16. if err != nil {
  17. panic(err)
  18. }
  19. defer file.Close()
  20. // 获取文件信息
  21. fileInfo, err := file.Stat()
  22. if err != nil {
  23. panic(err)
  24. }
  25. fileSize := fileInfo.Size()
  26. // 计算总块数
  27. totalChunks := (fileSize + chunkSize - 1) / chunkSize
  28. // 记录已上传的块(可以保存在文件或数据库中)
  29. uploadedChunks := make(map[int64]bool)
  30. // 遍历每个块并上传
  31. for chunkIndex := int64(0); chunkIndex < totalChunks; chunkIndex++ {
  32. if uploadedChunks[chunkIndex] {
  33. // 如果该块已经上传,则跳过
  34. continue
  35. }
  36. // 创建块的缓冲区
  37. buffer := make([]byte, chunkSize)
  38. readBytes, err := file.Read(buffer)
  39. if err != nil && err != io.EOF {
  40. panic(err)
  41. }
  42. if readBytes == 0 {
  43. break
  44. }
  45. // 上传块
  46. err = uploadChunk(buffer[:readBytes], chunkIndex, totalChunks, fileID, fileInfo.Name())
  47. if err != nil {
  48. fmt.Printf("Failed to upload chunk %d: %v\n", chunkIndex, err)
  49. continue
  50. }
  51. // 记录已上传块
  52. uploadedChunks[chunkIndex] = true
  53. }
  54. }
  55. func uploadChunk(chunkData []byte, chunkIndex, totalChunks int64, fileID, filename string) error {
  56. // 创建 multipart 请求体
  57. body := new(bytes.Buffer)
  58. writer := multipart.NewWriter(body)
  59. // 添加文件块
  60. part, err := writer.CreateFormFile("file", filename)
  61. if err != nil {
  62. return err
  63. }
  64. part.Write(chunkData)
  65. // 添加其他字段
  66. writer.WriteField("chunkIndex", fmt.Sprintf("%d", chunkIndex))
  67. writer.WriteField("totalChunks", fmt.Sprintf("%d", totalChunks))
  68. writer.WriteField("fileID", fileID)
  69. // 关闭 multipart 编写器
  70. err = writer.Close()
  71. if err != nil {
  72. return err
  73. }
  74. // 发送请求
  75. req, err := http.NewRequest("POST", "http://localhost:8080/upload", body)
  76. if err != nil {
  77. return err
  78. }
  79. req.Header.Set("Content-Type", writer.FormDataContentType())
  80. client := &http.Client{}
  81. resp, err := client.Do(req)
  82. if err != nil {
  83. return err
  84. }
  85. defer resp.Body.Close()
  86. // 读取响应
  87. respBody, err := io.ReadAll(resp.Body)
  88. if err != nil {
  89. return err
  90. }
  91. fmt.Printf("Response: %s\n", string(respBody))
  92. return nil
  93. }