file.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. package file
  2. import (
  3. "bufio"
  4. "bytes"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/fs"
  9. "io/ioutil"
  10. "log"
  11. "mime/multipart"
  12. "os"
  13. "path"
  14. path2 "path"
  15. "path/filepath"
  16. "strconv"
  17. "strings"
  18. "github.com/mholt/archiver/v3"
  19. )
  20. // GetSize get the file size
  21. func GetSize(f multipart.File) (int, error) {
  22. content, err := ioutil.ReadAll(f)
  23. return len(content), err
  24. }
  25. // GetExt get the file ext
  26. func GetExt(fileName string) string {
  27. return path.Ext(fileName)
  28. }
  29. // CheckNotExist check if the file exists
  30. func CheckNotExist(src string) bool {
  31. _, err := os.Stat(src)
  32. return os.IsNotExist(err)
  33. }
  34. // CheckPermission check if the file has permission
  35. func CheckPermission(src string) bool {
  36. _, err := os.Stat(src)
  37. return os.IsPermission(err)
  38. }
  39. // IsNotExistMkDir create a directory if it does not exist
  40. func IsNotExistMkDir(src string) error {
  41. if notExist := CheckNotExist(src); notExist {
  42. if err := MkDir(src); err != nil {
  43. return err
  44. }
  45. }
  46. return nil
  47. }
  48. // MkDir create a directory
  49. func MkDir(src string) error {
  50. err := os.MkdirAll(src, os.ModePerm)
  51. if err != nil {
  52. return err
  53. }
  54. os.Chmod(src, 0o777)
  55. return nil
  56. }
  57. // RMDir remove a directory
  58. func RMDir(src string) error {
  59. err := os.RemoveAll(src)
  60. if err != nil {
  61. return err
  62. }
  63. os.Remove(src)
  64. return nil
  65. }
  66. func RemoveAll(dir string) error {
  67. err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
  68. if err != nil {
  69. return err
  70. }
  71. if !info.IsDir() {
  72. return os.Remove(path)
  73. }
  74. return nil
  75. })
  76. if err != nil {
  77. return err
  78. }
  79. return os.Remove(dir)
  80. }
  81. // Open a file according to a specific mode
  82. func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
  83. f, err := os.OpenFile(name, flag, perm)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return f, nil
  88. }
  89. // MustOpen maximize trying to open the file
  90. func MustOpen(fileName, filePath string) (*os.File, error) {
  91. //dir, err := os.Getwd()
  92. //if err != nil {
  93. // return nil, fmt.Errorf("os.Getwd err: %v", err)
  94. //}
  95. src := filePath
  96. perm := CheckPermission(src)
  97. if perm == true {
  98. return nil, fmt.Errorf("file.CheckPermission Permission denied src: %s", src)
  99. }
  100. err := IsNotExistMkDir(src)
  101. if err != nil {
  102. return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
  103. }
  104. f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
  105. if err != nil {
  106. return nil, fmt.Errorf("Fail to OpenFile :%v", err)
  107. }
  108. return f, nil
  109. }
  110. // 判断所给路径文件/文件夹是否存在
  111. func Exists(path string) bool {
  112. _, err := os.Stat(path) // os.Stat获取文件信息
  113. if err != nil {
  114. if os.IsExist(err) {
  115. return true
  116. }
  117. return false
  118. }
  119. return true
  120. }
  121. // 判断所给路径是否为文件夹
  122. func IsDir(path string) bool {
  123. s, err := os.Stat(path)
  124. if err != nil {
  125. return false
  126. }
  127. return s.IsDir()
  128. }
  129. // 判断所给路径是否为文件
  130. func IsFile(path string) bool {
  131. return !IsDir(path)
  132. }
  133. func CreateFile(path string) error {
  134. file, err := os.Create(path)
  135. if err != nil {
  136. return err
  137. }
  138. defer file.Close()
  139. return nil
  140. }
  141. func CreateFileAndWriteContent(path string, content string) error {
  142. file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
  143. if err != nil {
  144. return err
  145. }
  146. defer file.Close()
  147. write := bufio.NewWriter(file)
  148. write.WriteString(content)
  149. write.Flush()
  150. return nil
  151. }
  152. // IsNotExistMkDir create a directory if it does not exist
  153. func IsNotExistCreateFile(src string) error {
  154. if notExist := CheckNotExist(src); notExist {
  155. if err := CreateFile(src); err != nil {
  156. return err
  157. }
  158. }
  159. return nil
  160. }
  161. func ReadFullFile(path string) []byte {
  162. file, err := os.Open(path)
  163. if err != nil {
  164. return []byte("")
  165. }
  166. defer file.Close()
  167. content, err := ioutil.ReadAll(file)
  168. if err != nil {
  169. return []byte("")
  170. }
  171. return content
  172. }
  173. // File copies a single file from src to dst
  174. func CopyFile(src, dst, style string) error {
  175. var err error
  176. var srcfd *os.File
  177. var dstfd *os.File
  178. var srcinfo os.FileInfo
  179. lastPath := src[strings.LastIndex(src, "/")+1:]
  180. if !strings.HasSuffix(dst, "/") {
  181. dst += "/"
  182. }
  183. dst += lastPath
  184. if Exists(dst) {
  185. if style == "skip" {
  186. return nil
  187. } else {
  188. os.Remove(dst)
  189. }
  190. }
  191. if srcfd, err = os.Open(src); err != nil {
  192. return err
  193. }
  194. defer srcfd.Close()
  195. if dstfd, err = os.Create(dst); err != nil {
  196. return err
  197. }
  198. defer dstfd.Close()
  199. if _, err = io.Copy(dstfd, srcfd); err != nil {
  200. return err
  201. }
  202. if srcinfo, err = os.Stat(src); err != nil {
  203. return err
  204. }
  205. return os.Chmod(dst, srcinfo.Mode())
  206. }
  207. /**
  208. * @description:
  209. * @param {*} src
  210. * @param {*} dst
  211. * @param {string} style
  212. * @return {*}
  213. * @method:
  214. * @router:
  215. */
  216. func CopySingleFile(src, dst, style string) error {
  217. var err error
  218. var srcfd *os.File
  219. var dstfd *os.File
  220. var srcinfo os.FileInfo
  221. if Exists(dst) {
  222. if style == "skip" {
  223. return nil
  224. } else {
  225. os.Remove(dst)
  226. }
  227. }
  228. if srcfd, err = os.Open(src); err != nil {
  229. return err
  230. }
  231. defer srcfd.Close()
  232. if dstfd, err = os.Create(dst); err != nil {
  233. return err
  234. }
  235. defer dstfd.Close()
  236. if _, err = io.Copy(dstfd, srcfd); err != nil {
  237. return err
  238. }
  239. if srcinfo, err = os.Stat(src); err != nil {
  240. return err
  241. }
  242. return os.Chmod(dst, srcinfo.Mode())
  243. }
  244. // Check for duplicate file names
  245. func GetNoDuplicateFileName(fullPath string) string {
  246. path, fileName := filepath.Split(fullPath)
  247. fileSuffix := path2.Ext(fileName)
  248. filenameOnly := strings.TrimSuffix(fileName, fileSuffix)
  249. for i := 0; Exists(fullPath); i++ {
  250. fullPath = path2.Join(path, filenameOnly+"("+strconv.Itoa(i+1)+")"+fileSuffix)
  251. }
  252. return fullPath
  253. }
  254. // Dir copies a whole directory recursively
  255. func CopyDir(src string, dst string, style string) error {
  256. var err error
  257. var fds []os.FileInfo
  258. var srcinfo os.FileInfo
  259. if srcinfo, err = os.Stat(src); err != nil {
  260. return err
  261. }
  262. if !srcinfo.IsDir() {
  263. if err = CopyFile(src, dst, style); err != nil {
  264. fmt.Println(err)
  265. }
  266. return nil
  267. }
  268. // dstPath := dst
  269. lastPath := src[strings.LastIndex(src, "/")+1:]
  270. dst += "/" + lastPath
  271. // for i := 0; Exists(dst); i++ {
  272. // dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
  273. // }
  274. if Exists(dst) {
  275. if style == "skip" {
  276. return nil
  277. } else {
  278. os.Remove(dst)
  279. }
  280. }
  281. if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
  282. return err
  283. }
  284. if fds, err = ioutil.ReadDir(src); err != nil {
  285. return err
  286. }
  287. for _, fd := range fds {
  288. srcfp := path.Join(src, fd.Name())
  289. dstfp := dst // path.Join(dst, fd.Name())
  290. if fd.IsDir() {
  291. if err = CopyDir(srcfp, dstfp, style); err != nil {
  292. fmt.Println(err)
  293. }
  294. } else {
  295. if err = CopyFile(srcfp, dstfp, style); err != nil {
  296. fmt.Println(err)
  297. }
  298. }
  299. }
  300. return nil
  301. }
  302. func WriteToPath(data []byte, path, name string) error {
  303. fullPath := path
  304. if strings.HasSuffix(path, "/") {
  305. fullPath += name
  306. } else {
  307. fullPath += "/" + name
  308. }
  309. return WriteToFullPath(data, fullPath, 0o666)
  310. }
  311. func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
  312. if err := IsNotExistCreateFile(fullPath); err != nil {
  313. return err
  314. }
  315. file, err := os.OpenFile(fullPath,
  316. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  317. perm,
  318. )
  319. if err != nil {
  320. return err
  321. }
  322. defer file.Close()
  323. _, err = file.Write(data)
  324. return err
  325. }
  326. // 最终拼接
  327. func SpliceFiles(dir, path string, length int, startPoint int) error {
  328. fullPath := path
  329. if err := IsNotExistCreateFile(fullPath); err != nil {
  330. return err
  331. }
  332. file, _ := os.OpenFile(fullPath,
  333. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  334. 0o666,
  335. )
  336. defer file.Close()
  337. bufferedWriter := bufio.NewWriter(file)
  338. // todo: here should have a goroutine to remove each partial file after it is read, to save disk space
  339. for i := 0; i < length+startPoint-1; i++ {
  340. data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
  341. if err != nil {
  342. return err
  343. }
  344. if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
  345. return err
  346. }
  347. }
  348. bufferedWriter.Flush()
  349. return nil
  350. }
  351. func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
  352. switch t {
  353. case "zip", "":
  354. return ".zip", archiver.NewZip(), nil
  355. case "tar":
  356. return ".tar", archiver.NewTar(), nil
  357. case "targz":
  358. return ".tar.gz", archiver.NewTarGz(), nil
  359. case "tarbz2":
  360. return ".tar.bz2", archiver.NewTarBz2(), nil
  361. case "tarxz":
  362. return ".tar.xz", archiver.NewTarXz(), nil
  363. case "tarlz4":
  364. return ".tar.lz4", archiver.NewTarLz4(), nil
  365. case "tarsz":
  366. return ".tar.sz", archiver.NewTarSz(), nil
  367. default:
  368. return "", nil, errors.New("format not implemented")
  369. }
  370. }
  371. func AddFile(ar archiver.Writer, path, commonPath string) error {
  372. info, err := os.Stat(path)
  373. if err != nil {
  374. return err
  375. }
  376. if !info.IsDir() && !info.Mode().IsRegular() {
  377. return nil
  378. }
  379. file, err := os.Open(path)
  380. if err != nil {
  381. return err
  382. }
  383. defer file.Close()
  384. if path != commonPath {
  385. //filename := info.Name()
  386. filename := strings.TrimPrefix(path, commonPath)
  387. filename = strings.TrimPrefix(filename, string(filepath.Separator))
  388. err = ar.Write(archiver.File{
  389. FileInfo: archiver.FileInfo{
  390. FileInfo: info,
  391. CustomName: filename,
  392. },
  393. ReadCloser: file,
  394. })
  395. if err != nil {
  396. return err
  397. }
  398. }
  399. if info.IsDir() {
  400. names, err := file.Readdirnames(0)
  401. if err != nil {
  402. return err
  403. }
  404. for _, name := range names {
  405. err = AddFile(ar, filepath.Join(path, name), commonPath)
  406. if err != nil {
  407. log.Printf("Failed to archive %v", err)
  408. }
  409. }
  410. }
  411. return nil
  412. }
  413. func CommonPrefix(sep byte, paths ...string) string {
  414. // Handle special cases.
  415. switch len(paths) {
  416. case 0:
  417. return ""
  418. case 1:
  419. return path.Clean(paths[0])
  420. }
  421. // Note, we treat string as []byte, not []rune as is often
  422. // done in Go. (And sep as byte, not rune). This is because
  423. // most/all supported OS' treat paths as string of non-zero
  424. // bytes. A filename may be displayed as a sequence of Unicode
  425. // runes (typically encoded as UTF-8) but paths are
  426. // not required to be valid UTF-8 or in any normalized form
  427. // (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
  428. // file names.
  429. c := []byte(path.Clean(paths[0]))
  430. // We add a trailing sep to handle the case where the
  431. // common prefix directory is included in the path list
  432. // (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
  433. // path.Clean will have cleaned off trailing / separators with
  434. // the exception of the root directory, "/" (in which case we
  435. // make it "//", but this will get fixed up to "/" bellow).
  436. c = append(c, sep)
  437. // Ignore the first path since it's already in c
  438. for _, v := range paths[1:] {
  439. // Clean up each path before testing it
  440. v = path.Clean(v) + string(sep)
  441. // Find the first non-common byte and truncate c
  442. if len(v) < len(c) {
  443. c = c[:len(v)]
  444. }
  445. for i := 0; i < len(c); i++ {
  446. if v[i] != c[i] {
  447. c = c[:i]
  448. break
  449. }
  450. }
  451. }
  452. // Remove trailing non-separator characters and the final separator
  453. for i := len(c) - 1; i >= 0; i-- {
  454. if c[i] == sep {
  455. c = c[:i]
  456. break
  457. }
  458. }
  459. return string(c)
  460. }
  461. func GetFileOrDirSize(path string) (int64, error) {
  462. fileInfo, err := os.Stat(path)
  463. if err != nil {
  464. return 0, err
  465. }
  466. if fileInfo.IsDir() {
  467. return DirSizeB(path + "/")
  468. }
  469. return fileInfo.Size(), nil
  470. }
  471. // getFileSize get file size by path(B)
  472. func DirSizeB(path string) (int64, error) {
  473. var size int64
  474. err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
  475. if !info.IsDir() {
  476. size += info.Size()
  477. }
  478. return err
  479. })
  480. return size, err
  481. }
  482. func MoveFile(sourcePath, destPath string) error {
  483. inputFile, err := os.Open(sourcePath)
  484. if err != nil {
  485. return fmt.Errorf("Couldn't open source file: %s", err)
  486. }
  487. outputFile, err := os.Create(destPath)
  488. if err != nil {
  489. inputFile.Close()
  490. return fmt.Errorf("Couldn't open dest file: %s", err)
  491. }
  492. defer outputFile.Close()
  493. _, err = io.Copy(outputFile, inputFile)
  494. inputFile.Close()
  495. if err != nil {
  496. return fmt.Errorf("Writing to output file failed: %s", err)
  497. }
  498. err = os.Remove(sourcePath)
  499. if err != nil {
  500. return fmt.Errorf("Failed removing original file: %s", err)
  501. }
  502. return nil
  503. }
  504. func ReadLine(lineNumber int, path string) string {
  505. file, err := os.Open(path)
  506. if err != nil {
  507. return ""
  508. }
  509. fileScanner := bufio.NewScanner(file)
  510. lineCount := 1
  511. for fileScanner.Scan() {
  512. if lineCount == lineNumber {
  513. return fileScanner.Text()
  514. }
  515. lineCount++
  516. }
  517. defer file.Close()
  518. return ""
  519. }
  520. func NameAccumulation(name string, dir string) string {
  521. path := filepath.Join(dir, name)
  522. if _, err := os.Stat(path); os.IsNotExist(err) {
  523. return name
  524. }
  525. base := name
  526. strings.Split(base, "_")
  527. index := strings.LastIndex(base, "_")
  528. if index < 0 {
  529. index = len(base)
  530. }
  531. for i := 1; ; i++ {
  532. newPath := filepath.Join(dir, fmt.Sprintf("%s_%d", base[:index], i))
  533. if _, err := os.Stat(newPath); os.IsNotExist(err) {
  534. return fmt.Sprintf("%s_%d", base[:index], i)
  535. }
  536. }
  537. }
  538. func ParseFileHeader(h []byte, boundary []byte) (map[string]string, bool) {
  539. arr := bytes.Split(h, boundary)
  540. //var out_header FileHeader
  541. //out_header.ContentLength = -1
  542. const (
  543. CONTENT_DISPOSITION = "Content-Disposition: "
  544. NAME = "name=\""
  545. FILENAME = "filename=\""
  546. CONTENT_TYPE = "Content-Type: "
  547. CONTENT_LENGTH = "Content-Length: "
  548. )
  549. result := make(map[string]string)
  550. for _, item := range arr {
  551. tarr := bytes.Split(item, []byte(";"))
  552. if len(tarr) != 2 {
  553. continue
  554. }
  555. tbyte := tarr[1]
  556. fmt.Println(string(tbyte))
  557. tbyte = bytes.ReplaceAll(tbyte, []byte("\r\n--"), []byte(""))
  558. tbyte = bytes.ReplaceAll(tbyte, []byte("name=\""), []byte(""))
  559. tempArr := bytes.Split(tbyte, []byte("\"\r\n\r\n"))
  560. if len(tempArr) != 2 {
  561. continue
  562. }
  563. bytes.HasPrefix(item, []byte("name="))
  564. result[strings.TrimSpace(string(tempArr[0]))] = strings.TrimSpace(string(tempArr[1]))
  565. }
  566. // for _, item := range arr {
  567. // if bytes.HasPrefix(item, []byte(CONTENT_DISPOSITION)) {
  568. // l := len(CONTENT_DISPOSITION)
  569. // arr1 := bytes.Split(item[l:], []byte("; "))
  570. // out_header.ContentDisposition = string(arr1[0])
  571. // if bytes.HasPrefix(arr1[1], []byte(NAME)) {
  572. // out_header.Name = string(arr1[1][len(NAME) : len(arr1[1])-1])
  573. // }
  574. // l = len(arr1[2])
  575. // if bytes.HasPrefix(arr1[2], []byte(FILENAME)) && arr1[2][l-1] == 0x22 {
  576. // out_header.FileName = string(arr1[2][len(FILENAME) : l-1])
  577. // }
  578. // } else if bytes.HasPrefix(item, []byte(CONTENT_TYPE)) {
  579. // l := len(CONTENT_TYPE)
  580. // out_header.ContentType = string(item[l:])
  581. // } else if bytes.HasPrefix(item, []byte(CONTENT_LENGTH)) {
  582. // l := len(CONTENT_LENGTH)
  583. // s := string(item[l:])
  584. // content_length, err := strconv.ParseInt(s, 10, 64)
  585. // if err != nil {
  586. // log.Printf("content length error:%s", string(item))
  587. // return out_header, false
  588. // } else {
  589. // out_header.ContentLength = content_length
  590. // }
  591. // } else {
  592. // log.Printf("unknown:%s\n", string(item))
  593. // }
  594. // }
  595. //fmt.Println(result)
  596. // if len(out_header.FileName) == 0 {
  597. // return out_header, false
  598. // }
  599. return result, true
  600. }
  601. func ReadToBoundary(boundary []byte, stream io.ReadCloser, target io.WriteCloser) ([]byte, bool, error) {
  602. read_data := make([]byte, 1024*8)
  603. read_data_len := 0
  604. buf := make([]byte, 1024*4)
  605. b_len := len(boundary)
  606. reach_end := false
  607. for !reach_end {
  608. read_len, err := stream.Read(buf)
  609. if err != nil {
  610. if err != io.EOF && read_len <= 0 {
  611. return nil, true, err
  612. }
  613. reach_end = true
  614. }
  615. copy(read_data[read_data_len:], buf[:read_len])
  616. read_data_len += read_len
  617. if read_data_len < b_len+4 {
  618. continue
  619. }
  620. loc := bytes.Index(read_data[:read_data_len], boundary)
  621. if loc >= 0 {
  622. target.Write(read_data[:loc-4])
  623. return read_data[loc:read_data_len], reach_end, nil
  624. }
  625. target.Write(read_data[:read_data_len-b_len-4])
  626. copy(read_data[0:], read_data[read_data_len-b_len-4:])
  627. read_data_len = b_len + 4
  628. }
  629. target.Write(read_data[:read_data_len])
  630. return nil, reach_end, nil
  631. }
  632. func ParseFromHead(read_data []byte, read_total int, boundary []byte, stream io.ReadCloser) (map[string]string, []byte, error) {
  633. buf := make([]byte, 1024*8)
  634. found_boundary := false
  635. boundary_loc := -1
  636. for {
  637. read_len, err := stream.Read(buf)
  638. if err != nil {
  639. if err != io.EOF {
  640. return nil, nil, err
  641. }
  642. break
  643. }
  644. if read_total+read_len > cap(read_data) {
  645. return nil, nil, fmt.Errorf("not found boundary")
  646. }
  647. copy(read_data[read_total:], buf[:read_len])
  648. read_total += read_len
  649. if !found_boundary {
  650. boundary_loc = bytes.LastIndex(read_data[:read_total], boundary)
  651. if boundary_loc == -1 {
  652. continue
  653. }
  654. found_boundary = true
  655. }
  656. start_loc := boundary_loc + len(boundary)
  657. fmt.Println(string(read_data))
  658. file_head_loc := bytes.Index(read_data[start_loc:read_total], []byte("\r\n\r\n"))
  659. if file_head_loc == -1 {
  660. continue
  661. }
  662. file_head_loc += start_loc
  663. ret := false
  664. headMap, ret := ParseFileHeader(read_data, boundary)
  665. if !ret {
  666. return headMap, nil, fmt.Errorf("ParseFileHeader fail:%s", string(read_data[start_loc:file_head_loc]))
  667. }
  668. return headMap, read_data[file_head_loc+4 : read_total], nil
  669. }
  670. return nil, nil, fmt.Errorf("reach to sream EOF")
  671. }