file.go 10 KB

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