file.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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 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. dstPath := dst
  167. dst += lastPath
  168. for i := 0; Exists(dst); i++ {
  169. name := strings.Split(lastPath, ".")
  170. nameIndex := 0
  171. if len(name) > 2 {
  172. nameIndex = len(name) - 2
  173. }
  174. name[nameIndex] = name[nameIndex] + "(Copy)"
  175. dst = dstPath
  176. for _, v := range name {
  177. dst += v + "."
  178. }
  179. dst = strings.TrimSuffix(dst, ".")
  180. }
  181. if srcfd, err = os.Open(src); err != nil {
  182. return err
  183. }
  184. defer srcfd.Close()
  185. if dstfd, err = os.Create(dst); err != nil {
  186. return err
  187. }
  188. defer dstfd.Close()
  189. if _, err = io.Copy(dstfd, srcfd); err != nil {
  190. return err
  191. }
  192. if srcinfo, err = os.Stat(src); err != nil {
  193. return err
  194. }
  195. return os.Chmod(dst, srcinfo.Mode())
  196. }
  197. //Check for duplicate file names
  198. func GetNoDuplicateFileName(fullPath string) string {
  199. path, fileName := filepath.Split(fullPath)
  200. fileSuffix := path2.Ext(fileName)
  201. filenameOnly := strings.TrimSuffix(fileName, fileSuffix)
  202. for i := 0; Exists(fullPath); i++ {
  203. fullPath = path2.Join(path, filenameOnly+"("+strconv.Itoa(i+1)+")"+fileSuffix)
  204. }
  205. return fullPath
  206. }
  207. // Dir copies a whole directory recursively
  208. func CopyDir(src string, dst string) error {
  209. var err error
  210. var fds []os.FileInfo
  211. var srcinfo os.FileInfo
  212. if srcinfo, err = os.Stat(src); err != nil {
  213. return err
  214. }
  215. if !srcinfo.IsDir() {
  216. if err = CopyFile(src, dst); err != nil {
  217. fmt.Println(err)
  218. }
  219. return nil
  220. }
  221. dstPath := dst
  222. lastPath := src[strings.LastIndex(src, "/")+1:]
  223. dst += "/" + lastPath
  224. for i := 0; Exists(dst); i++ {
  225. dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
  226. }
  227. if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
  228. return err
  229. }
  230. if fds, err = ioutil.ReadDir(src); err != nil {
  231. return err
  232. }
  233. for _, fd := range fds {
  234. srcfp := path.Join(src, fd.Name())
  235. dstfp := dst //path.Join(dst, fd.Name())
  236. if fd.IsDir() {
  237. if err = CopyDir(srcfp, dstfp); err != nil {
  238. fmt.Println(err)
  239. }
  240. } else {
  241. if err = CopyFile(srcfp, dstfp); err != nil {
  242. fmt.Println(err)
  243. }
  244. }
  245. }
  246. return nil
  247. }
  248. func WriteToPath(data []byte, path, name string) error {
  249. fullPath := path
  250. if strings.HasSuffix(path, "/") {
  251. fullPath += name
  252. } else {
  253. fullPath += "/" + name
  254. }
  255. IsNotExistCreateFile(fullPath)
  256. file, err := os.OpenFile(fullPath,
  257. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  258. 0666,
  259. )
  260. if err != nil {
  261. return err
  262. }
  263. defer file.Close()
  264. _, err = file.Write(data)
  265. return err
  266. }
  267. //最终拼接
  268. func SpliceFiles(dir, path string, length int, startPoint int) error {
  269. fullPath := path
  270. IsNotExistCreateFile(fullPath)
  271. file, _ := os.OpenFile(fullPath,
  272. os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
  273. 0666,
  274. )
  275. defer file.Close()
  276. bufferedWriter := bufio.NewWriter(file)
  277. for i := 0; i < length+startPoint; i++ {
  278. data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
  279. if err != nil {
  280. return err
  281. }
  282. _, err = bufferedWriter.Write(data)
  283. if err != nil {
  284. return err
  285. }
  286. }
  287. bufferedWriter.Flush()
  288. return nil
  289. }
  290. func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
  291. switch t {
  292. case "zip", "":
  293. return ".zip", archiver.NewZip(), nil
  294. case "tar":
  295. return ".tar", archiver.NewTar(), nil
  296. case "targz":
  297. return ".tar.gz", archiver.NewTarGz(), nil
  298. case "tarbz2":
  299. return ".tar.bz2", archiver.NewTarBz2(), nil
  300. case "tarxz":
  301. return ".tar.xz", archiver.NewTarXz(), nil
  302. case "tarlz4":
  303. return ".tar.lz4", archiver.NewTarLz4(), nil
  304. case "tarsz":
  305. return ".tar.sz", archiver.NewTarSz(), nil
  306. default:
  307. return "", nil, errors.New("format not implemented")
  308. }
  309. }
  310. func AddFile(ar archiver.Writer, path, commonPath string) error {
  311. info, err := os.Stat(path)
  312. if err != nil {
  313. return err
  314. }
  315. if !info.IsDir() && !info.Mode().IsRegular() {
  316. return nil
  317. }
  318. file, err := os.Open(path)
  319. if err != nil {
  320. return err
  321. }
  322. defer file.Close()
  323. if path != commonPath {
  324. filename := info.Name()
  325. err = ar.Write(archiver.File{
  326. FileInfo: archiver.FileInfo{
  327. FileInfo: info,
  328. CustomName: filename,
  329. },
  330. ReadCloser: file,
  331. })
  332. if err != nil {
  333. return err
  334. }
  335. }
  336. if info.IsDir() {
  337. names, err := file.Readdirnames(0)
  338. if err != nil {
  339. return err
  340. }
  341. for _, name := range names {
  342. err = AddFile(ar, filepath.Join(path, name), commonPath)
  343. if err != nil {
  344. log.Printf("Failed to archive %v", err)
  345. }
  346. }
  347. }
  348. return nil
  349. }
  350. func CommonPrefix(sep byte, paths ...string) string {
  351. // Handle special cases.
  352. switch len(paths) {
  353. case 0:
  354. return ""
  355. case 1:
  356. return path.Clean(paths[0])
  357. }
  358. // Note, we treat string as []byte, not []rune as is often
  359. // done in Go. (And sep as byte, not rune). This is because
  360. // most/all supported OS' treat paths as string of non-zero
  361. // bytes. A filename may be displayed as a sequence of Unicode
  362. // runes (typically encoded as UTF-8) but paths are
  363. // not required to be valid UTF-8 or in any normalized form
  364. // (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
  365. // file names.
  366. c := []byte(path.Clean(paths[0]))
  367. // We add a trailing sep to handle the case where the
  368. // common prefix directory is included in the path list
  369. // (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
  370. // path.Clean will have cleaned off trailing / separators with
  371. // the exception of the root directory, "/" (in which case we
  372. // make it "//", but this will get fixed up to "/" bellow).
  373. c = append(c, sep)
  374. // Ignore the first path since it's already in c
  375. for _, v := range paths[1:] {
  376. // Clean up each path before testing it
  377. v = path.Clean(v) + string(sep)
  378. // Find the first non-common byte and truncate c
  379. if len(v) < len(c) {
  380. c = c[:len(v)]
  381. }
  382. for i := 0; i < len(c); i++ {
  383. if v[i] != c[i] {
  384. c = c[:i]
  385. break
  386. }
  387. }
  388. }
  389. // Remove trailing non-separator characters and the final separator
  390. for i := len(c) - 1; i >= 0; i-- {
  391. if c[i] == sep {
  392. c = c[:i]
  393. break
  394. }
  395. }
  396. return string(c)
  397. }
  398. func GetFileOrDirSize(path string) (int64, error) {
  399. fileInfo, err := os.Stat(path)
  400. if err != nil {
  401. return 0, err
  402. }
  403. if fileInfo.IsDir() {
  404. return DirSizeB(path + "/")
  405. }
  406. return fileInfo.Size(), nil
  407. }
  408. //getFileSize get file size by path(B)
  409. func DirSizeB(path string) (int64, error) {
  410. var size int64
  411. err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
  412. if !info.IsDir() {
  413. size += info.Size()
  414. }
  415. return err
  416. })
  417. return size, err
  418. }