file.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. package file
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "io/fs"
  8. "io/ioutil"
  9. "log"
  10. "mime/multipart"
  11. "os"
  12. "path"
  13. path2 "path"
  14. "path/filepath"
  15. "strconv"
  16. "strings"
  17. "github.com/mholt/archiver/v3"
  18. )
  19. // GetSize get the file size
  20. func GetSize(f multipart.File) (int, error) {
  21. content, err := ioutil.ReadAll(f)
  22. return len(content), err
  23. }
  24. // GetExt get the file ext
  25. func GetExt(fileName string) string {
  26. return path.Ext(fileName)
  27. }
  28. // CheckNotExist check if the file exists
  29. func CheckNotExist(src string) bool {
  30. _, err := os.Stat(src)
  31. return os.IsNotExist(err)
  32. }
  33. // CheckPermission check if the file has permission
  34. func CheckPermission(src string) bool {
  35. _, err := os.Stat(src)
  36. return os.IsPermission(err)
  37. }
  38. // IsNotExistMkDir create a directory if it does not exist
  39. func IsNotExistMkDir(src string) error {
  40. if notExist := CheckNotExist(src); notExist {
  41. if err := MkDir(src); err != nil {
  42. return err
  43. }
  44. }
  45. return nil
  46. }
  47. // MkDir create a directory
  48. func MkDir(src string) error {
  49. err := os.MkdirAll(src, os.ModePerm)
  50. if err != nil {
  51. return err
  52. }
  53. os.Chmod(src, 0o777)
  54. return nil
  55. }
  56. // RMDir remove a directory
  57. func RMDir(src string) error {
  58. err := os.RemoveAll(src)
  59. if err != nil {
  60. return err
  61. }
  62. os.Remove(src)
  63. return nil
  64. }
  65. // Open a file according to a specific mode
  66. func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
  67. f, err := os.OpenFile(name, flag, perm)
  68. if err != nil {
  69. return nil, err
  70. }
  71. return f, nil
  72. }
  73. // MustOpen maximize trying to open the file
  74. func MustOpen(fileName, filePath string) (*os.File, error) {
  75. //dir, err := os.Getwd()
  76. //if err != nil {
  77. // return nil, fmt.Errorf("os.Getwd err: %v", err)
  78. //}
  79. src := filePath
  80. perm := CheckPermission(src)
  81. if perm == true {
  82. return nil, fmt.Errorf("file.CheckPermission Permission denied src: %s", src)
  83. }
  84. err := IsNotExistMkDir(src)
  85. if err != nil {
  86. return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
  87. }
  88. f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
  89. if err != nil {
  90. return nil, fmt.Errorf("Fail to OpenFile :%v", err)
  91. }
  92. return f, nil
  93. }
  94. // 判断所给路径文件/文件夹是否存在
  95. func Exists(path string) bool {
  96. _, err := os.Stat(path) // os.Stat获取文件信息
  97. if err != nil {
  98. if os.IsExist(err) {
  99. return true
  100. }
  101. return false
  102. }
  103. return true
  104. }
  105. // 判断所给路径是否为文件夹
  106. func IsDir(path string) bool {
  107. s, err := os.Stat(path)
  108. if err != nil {
  109. return false
  110. }
  111. return s.IsDir()
  112. }
  113. // 判断所给路径是否为文件
  114. func IsFile(path string) bool {
  115. return !IsDir(path)
  116. }
  117. func CreateFile(path string) error {
  118. file, err := os.Create(path)
  119. if err != nil {
  120. return err
  121. }
  122. defer file.Close()
  123. return nil
  124. }
  125. func CreateFileAndWriteContent(path string, content string) error {
  126. file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
  127. if err != nil {
  128. return err
  129. }
  130. defer file.Close()
  131. write := bufio.NewWriter(file)
  132. write.WriteString(content)
  133. write.Flush()
  134. return nil
  135. }
  136. // IsNotExistMkDir create a directory if it does not exist
  137. func IsNotExistCreateFile(src string) error {
  138. if notExist := CheckNotExist(src); notExist {
  139. if err := CreateFile(src); err != nil {
  140. return err
  141. }
  142. }
  143. return nil
  144. }
  145. func ReadFullFile(path string) []byte {
  146. file, err := os.Open(path)
  147. if err != nil {
  148. return []byte("")
  149. }
  150. defer file.Close()
  151. content, err := ioutil.ReadAll(file)
  152. if err != nil {
  153. return []byte("")
  154. }
  155. return content
  156. }
  157. // File copies a single file from src to dst
  158. func CopyFile(src, dst, style string) error {
  159. var err error
  160. var srcfd *os.File
  161. var dstfd *os.File
  162. var srcinfo os.FileInfo
  163. lastPath := src[strings.LastIndex(src, "/")+1:]
  164. if !strings.HasSuffix(dst, "/") {
  165. dst += "/"
  166. }
  167. dst += lastPath
  168. if Exists(dst) {
  169. if style == "skip" {
  170. return nil
  171. } else {
  172. os.Remove(dst)
  173. }
  174. }
  175. if srcfd, err = os.Open(src); err != nil {
  176. return err
  177. }
  178. defer srcfd.Close()
  179. if dstfd, err = os.Create(dst); err != nil {
  180. return err
  181. }
  182. defer dstfd.Close()
  183. if _, err = io.Copy(dstfd, srcfd); err != nil {
  184. return err
  185. }
  186. if srcinfo, err = os.Stat(src); err != nil {
  187. return err
  188. }
  189. return os.Chmod(dst, srcinfo.Mode())
  190. }
  191. /**
  192. * @description:
  193. * @param {*} src
  194. * @param {*} dst
  195. * @param {string} style
  196. * @return {*}
  197. * @method:
  198. * @router:
  199. */
  200. func CopySingleFile(src, dst, style string) error {
  201. var err error
  202. var srcfd *os.File
  203. var dstfd *os.File
  204. var srcinfo os.FileInfo
  205. if Exists(dst) {
  206. if style == "skip" {
  207. return nil
  208. } else {
  209. os.Remove(dst)
  210. }
  211. }
  212. if srcfd, err = os.Open(src); err != nil {
  213. return err
  214. }
  215. defer srcfd.Close()
  216. if dstfd, err = os.Create(dst); err != nil {
  217. return err
  218. }
  219. defer dstfd.Close()
  220. if _, err = io.Copy(dstfd, srcfd); err != nil {
  221. return err
  222. }
  223. if srcinfo, err = os.Stat(src); err != nil {
  224. return err
  225. }
  226. return os.Chmod(dst, srcinfo.Mode())
  227. }
  228. // Check for duplicate file names
  229. func GetNoDuplicateFileName(fullPath string) string {
  230. path, fileName := filepath.Split(fullPath)
  231. fileSuffix := path2.Ext(fileName)
  232. filenameOnly := strings.TrimSuffix(fileName, fileSuffix)
  233. for i := 0; Exists(fullPath); i++ {
  234. fullPath = path2.Join(path, filenameOnly+"("+strconv.Itoa(i+1)+")"+fileSuffix)
  235. }
  236. return fullPath
  237. }
  238. // Dir copies a whole directory recursively
  239. func CopyDir(src string, dst string, style string) error {
  240. var err error
  241. var fds []os.FileInfo
  242. var srcinfo os.FileInfo
  243. if srcinfo, err = os.Stat(src); err != nil {
  244. return err
  245. }
  246. if !srcinfo.IsDir() {
  247. if err = CopyFile(src, dst, style); err != nil {
  248. fmt.Println(err)
  249. }
  250. return nil
  251. }
  252. // dstPath := dst
  253. lastPath := src[strings.LastIndex(src, "/")+1:]
  254. dst += "/" + lastPath
  255. // for i := 0; Exists(dst); i++ {
  256. // dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
  257. // }
  258. if Exists(dst) {
  259. if style == "skip" {
  260. return nil
  261. } else {
  262. os.Remove(dst)
  263. }
  264. }
  265. if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
  266. return err
  267. }
  268. if fds, err = ioutil.ReadDir(src); err != nil {
  269. return err
  270. }
  271. for _, fd := range fds {
  272. srcfp := path.Join(src, fd.Name())
  273. dstfp := dst // path.Join(dst, fd.Name())
  274. if fd.IsDir() {
  275. if err = CopyDir(srcfp, dstfp, style); err != nil {
  276. fmt.Println(err)
  277. }
  278. } else {
  279. if err = CopyFile(srcfp, dstfp, style); err != nil {
  280. fmt.Println(err)
  281. }
  282. }
  283. }
  284. return nil
  285. }
  286. func WriteToPath(data []byte, path, name string) error {
  287. fullPath := path
  288. if strings.HasSuffix(path, "/") {
  289. fullPath += name
  290. } else {
  291. fullPath += "/" + name
  292. }
  293. return WriteToFullPath(data, fullPath, 0o666)
  294. }
  295. func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
  296. if err := IsNotExistCreateFile(fullPath); err != nil {
  297. return err
  298. }
  299. file, err := os.OpenFile(fullPath,
  300. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  301. perm,
  302. )
  303. if err != nil {
  304. return err
  305. }
  306. defer file.Close()
  307. _, err = file.Write(data)
  308. return err
  309. }
  310. // 最终拼接
  311. func SpliceFiles(dir, path string, length int, startPoint int) error {
  312. fullPath := path
  313. IsNotExistCreateFile(fullPath)
  314. file, _ := os.OpenFile(fullPath,
  315. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  316. 0o666,
  317. )
  318. defer file.Close()
  319. bufferedWriter := bufio.NewWriter(file)
  320. for i := 0; i < length+startPoint; i++ {
  321. data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
  322. if err != nil {
  323. return err
  324. }
  325. _, err = bufferedWriter.Write(data)
  326. if err != nil {
  327. return err
  328. }
  329. }
  330. bufferedWriter.Flush()
  331. return nil
  332. }
  333. func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
  334. switch t {
  335. case "zip", "":
  336. return ".zip", archiver.NewZip(), nil
  337. case "tar":
  338. return ".tar", archiver.NewTar(), nil
  339. case "targz":
  340. return ".tar.gz", archiver.NewTarGz(), nil
  341. case "tarbz2":
  342. return ".tar.bz2", archiver.NewTarBz2(), nil
  343. case "tarxz":
  344. return ".tar.xz", archiver.NewTarXz(), nil
  345. case "tarlz4":
  346. return ".tar.lz4", archiver.NewTarLz4(), nil
  347. case "tarsz":
  348. return ".tar.sz", archiver.NewTarSz(), nil
  349. default:
  350. return "", nil, errors.New("format not implemented")
  351. }
  352. }
  353. func AddFile(ar archiver.Writer, path, commonPath string) error {
  354. info, err := os.Stat(path)
  355. if err != nil {
  356. return err
  357. }
  358. if !info.IsDir() && !info.Mode().IsRegular() {
  359. return nil
  360. }
  361. file, err := os.Open(path)
  362. if err != nil {
  363. return err
  364. }
  365. defer file.Close()
  366. if path != commonPath {
  367. filename := info.Name()
  368. err = ar.Write(archiver.File{
  369. FileInfo: archiver.FileInfo{
  370. FileInfo: info,
  371. CustomName: filename,
  372. },
  373. ReadCloser: file,
  374. })
  375. if err != nil {
  376. return err
  377. }
  378. }
  379. if info.IsDir() {
  380. names, err := file.Readdirnames(0)
  381. if err != nil {
  382. return err
  383. }
  384. for _, name := range names {
  385. err = AddFile(ar, filepath.Join(path, name), commonPath)
  386. if err != nil {
  387. log.Printf("Failed to archive %v", err)
  388. }
  389. }
  390. }
  391. return nil
  392. }
  393. func CommonPrefix(sep byte, paths ...string) string {
  394. // Handle special cases.
  395. switch len(paths) {
  396. case 0:
  397. return ""
  398. case 1:
  399. return path.Clean(paths[0])
  400. }
  401. // Note, we treat string as []byte, not []rune as is often
  402. // done in Go. (And sep as byte, not rune). This is because
  403. // most/all supported OS' treat paths as string of non-zero
  404. // bytes. A filename may be displayed as a sequence of Unicode
  405. // runes (typically encoded as UTF-8) but paths are
  406. // not required to be valid UTF-8 or in any normalized form
  407. // (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
  408. // file names.
  409. c := []byte(path.Clean(paths[0]))
  410. // We add a trailing sep to handle the case where the
  411. // common prefix directory is included in the path list
  412. // (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
  413. // path.Clean will have cleaned off trailing / separators with
  414. // the exception of the root directory, "/" (in which case we
  415. // make it "//", but this will get fixed up to "/" bellow).
  416. c = append(c, sep)
  417. // Ignore the first path since it's already in c
  418. for _, v := range paths[1:] {
  419. // Clean up each path before testing it
  420. v = path.Clean(v) + string(sep)
  421. // Find the first non-common byte and truncate c
  422. if len(v) < len(c) {
  423. c = c[:len(v)]
  424. }
  425. for i := 0; i < len(c); i++ {
  426. if v[i] != c[i] {
  427. c = c[:i]
  428. break
  429. }
  430. }
  431. }
  432. // Remove trailing non-separator characters and the final separator
  433. for i := len(c) - 1; i >= 0; i-- {
  434. if c[i] == sep {
  435. c = c[:i]
  436. break
  437. }
  438. }
  439. return string(c)
  440. }
  441. func GetFileOrDirSize(path string) (int64, error) {
  442. fileInfo, err := os.Stat(path)
  443. if err != nil {
  444. return 0, err
  445. }
  446. if fileInfo.IsDir() {
  447. return DirSizeB(path + "/")
  448. }
  449. return fileInfo.Size(), nil
  450. }
  451. // getFileSize get file size by path(B)
  452. func DirSizeB(path string) (int64, error) {
  453. var size int64
  454. err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
  455. if !info.IsDir() {
  456. size += info.Size()
  457. }
  458. return err
  459. })
  460. return size, err
  461. }
  462. func MoveFile(sourcePath, destPath string) error {
  463. inputFile, err := os.Open(sourcePath)
  464. if err != nil {
  465. return fmt.Errorf("Couldn't open source file: %s", err)
  466. }
  467. outputFile, err := os.Create(destPath)
  468. if err != nil {
  469. inputFile.Close()
  470. return fmt.Errorf("Couldn't open dest file: %s", err)
  471. }
  472. defer outputFile.Close()
  473. _, err = io.Copy(outputFile, inputFile)
  474. inputFile.Close()
  475. if err != nil {
  476. return fmt.Errorf("Writing to output file failed: %s", err)
  477. }
  478. err = os.Remove(sourcePath)
  479. if err != nil {
  480. return fmt.Errorf("Failed removing original file: %s", err)
  481. }
  482. return nil
  483. }
  484. func ReadLine(lineNumber int, path string) string {
  485. file, err := os.Open(path)
  486. if err != nil {
  487. return ""
  488. }
  489. fileScanner := bufio.NewScanner(file)
  490. lineCount := 1
  491. for fileScanner.Scan() {
  492. if lineCount == lineNumber {
  493. return fileScanner.Text()
  494. }
  495. lineCount++
  496. }
  497. defer file.Close()
  498. return ""
  499. }