feat: 增加文件压缩功能

This commit is contained in:
zhengkunwang223 2022-08-30 17:59:59 +08:00
parent 12527de2ba
commit 20129c7d0b
20 changed files with 442 additions and 30 deletions

View File

@ -76,3 +76,17 @@ func (b *BaseApi) ChangeFileMode(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) CompressFile(c *gin.Context) {
var req dto.FileCompress
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
err := fileService.Compress(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

View File

@ -30,3 +30,11 @@ type FileDelete struct {
Path string
IsDir bool
}
type FileCompress struct {
Files []string
Dst string
Type string
Name string
Replace bool
}

View File

@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"io"
"io/fs"
"path/filepath"
)
type FileService struct {
@ -75,6 +76,15 @@ func (f FileService) ChangeMode(op dto.FileCreate) error {
return fo.Chmod(op.Path, fs.FileMode(op.Mode))
}
func (f FileService) Compress(c dto.FileCompress) error {
fo := files.NewFileOp()
if !c.Replace && fo.Stat(filepath.Join(c.Dst, c.Name)) {
return errors.New("file is exist")
}
return fo.Compress(c.Files, c.Dst, c.Name, files.CompressType(c.Type))
}
func getUuid() string {
b := make([]byte, 16)
io.ReadFull(rand.Reader, b)

View File

@ -38,10 +38,13 @@ require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/dgraph-io/ristretto v0.1.0 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
@ -56,7 +59,7 @@ require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
@ -64,26 +67,33 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.12.3 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/mholt/archiver/v4 v4.0.0-alpha.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/tools v0.1.10 // indirect
google.golang.org/protobuf v1.28.0 // indirect

View File

@ -48,6 +48,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@ -77,6 +79,9 @@ github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/Lu
github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -91,6 +96,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 h1:6VSn3hB5U5GeA6kQw4TwWIWbOhtvR2hmbBJnTOtqTWc=
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6/go.mod h1:YxOVT5+yHzKvwhsiSIWmbAYM3Dr9AEEbER2dVayfBkg=
github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q=
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
@ -173,6 +180,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=
@ -250,8 +259,14 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -278,6 +293,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mholt/archiver/v4 v4.0.0-alpha.7 h1:xzByj8G8tj0Oq7ZYYU4+ixL/CVb5ruWCm0EZQ1PjOkE=
github.com/mholt/archiver/v4 v4.0.0-alpha.7/go.mod h1:Fs8qUkO74HHaidabihzYephJH8qmGD/nCP6tE5xC9BM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@ -295,6 +312,8 @@ github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6Yf
github.com/nicksnyder/go-i18n/v2 v2.1.2 h1:QHYxcUJnGHBaq7XbvgunmZ2Pn0focXFqTD61CkH146c=
github.com/nicksnyder/go-i18n/v2 v2.1.2/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
@ -306,6 +325,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -367,12 +388,17 @@ github.com/swaggo/gin-swagger v1.5.1/go.mod h1:Cbj/MlHApPOjZdf4joWFXLLgmZVPyh54G
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
github.com/swaggo/swag v1.8.4 h1:oGB351qH1JqUqK1tsMYEE5qTBbPk394BhsZxmUfebcI=
github.com/swaggo/swag v1.8.4/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg=
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -475,6 +501,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -539,6 +567,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -20,6 +20,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
fileRouter.POST("", baseApi.CreateFile)
fileRouter.POST("/del", baseApi.DeleteFile)
fileRouter.POST("/mode", baseApi.ChangeFileMode)
fileRouter.POST("/compress", baseApi.CompressFile)
}
}

View File

@ -1,11 +1,14 @@
package files
import (
"context"
"github.com/mholt/archiver/v4"
"github.com/spf13/afero"
"io"
"io/fs"
"os"
"path"
"path/filepath"
)
type FileOp struct {
@ -62,3 +65,95 @@ func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error {
func (f FileOp) Chmod(dst string, mode fs.FileMode) error {
return f.Fs.Chmod(dst, mode)
}
type CompressType string
const (
Zip CompressType = "zip"
Gz CompressType = "gz"
Bz2 CompressType = "bz2"
Tar CompressType = "tar"
TarGz CompressType = "tarGz"
Xz CompressType = "xz"
)
func getFormat(cType CompressType) archiver.CompressedArchive {
format := archiver.CompressedArchive{}
switch cType {
case Tar:
format.Archival = archiver.Tar{}
case TarGz, Gz:
format.Compression = archiver.Gz{}
format.Archival = archiver.Tar{}
case Zip:
format.Archival = archiver.Zip{}
case Bz2:
format.Compression = archiver.Bz2{}
format.Archival = archiver.Tar{}
case Xz:
format.Compression = archiver.Xz{}
format.Archival = archiver.Tar{}
}
return format
}
func (f FileOp) Compress(srcRiles []string, dst string, name string, cType CompressType) error {
format := getFormat(cType)
fileMaps := make(map[string]string, len(srcRiles))
for _, s := range srcRiles {
base := filepath.Base(s)
fileMaps[s] = base
}
files, err := archiver.FilesFromDisk(nil, fileMaps)
if err != nil {
return err
}
dstFile := filepath.Join(dst, name)
out, err := f.Fs.Create(dstFile)
if err != nil {
return err
}
err = format.Archive(context.Background(), out, files)
if err != nil {
return err
}
return nil
}
func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error {
format := getFormat(cType)
handler := func(ctx context.Context, archFile archiver.File) error {
info := archFile.FileInfo
filePath := filepath.Join(dst, archFile.NameInArchive)
if archFile.FileInfo.IsDir() {
if err := f.Fs.MkdirAll(filePath, info.Mode()); err != nil {
return err
}
return nil
}
fr, err := archFile.Open()
if err != nil {
return err
}
defer fr.Close()
fw, err := f.Fs.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, info.Mode())
if err != nil {
return err
}
defer fw.Close()
if _, err := io.Copy(fw, fr); err != nil {
return err
}
return nil
}
input, err := f.Fs.Open(srcFile)
if err != nil {
return err
}
return format.Extract(context.Background(), input, nil, handler)
}

View File

@ -23,6 +23,7 @@ type FileInfo struct {
IsSymlink bool `json:"isSymlink"`
Type string `json:"type"`
Mode string `json:"mode"`
MimeType string `json:"mimeType"`
UpdateTime time.Time `json:"updateTime"`
ModTime time.Time `json:"modTime"`
FileMode os.FileMode `json:"-"`
@ -56,6 +57,7 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
Mode: fmt.Sprintf("%04o", info.Mode().Perm()),
User: GetUsername(info.Sys().(*syscall.Stat_t).Uid),
Group: GetGroup(info.Sys().(*syscall.Stat_t).Gid),
MimeType: GetMimeType(op.Path),
}
if op.Expand {
if file.IsDir {
@ -107,6 +109,7 @@ func (f *FileInfo) listChildren() error {
Mode: fmt.Sprintf("%04o", df.Mode().Perm()),
User: GetUsername(df.Sys().(*syscall.Stat_t).Uid),
Group: GetGroup(df.Sys().(*syscall.Stat_t).Gid),
MimeType: GetMimeType(fPath),
}
if isInvalidLink {

View File

@ -1,6 +1,7 @@
package files
import (
"github.com/gabriel-vasile/mimetype"
"os"
"os/user"
"strconv"
@ -25,3 +26,11 @@ func GetGroup(gid uint32) string {
}
return usr.Name
}
func GetMimeType(path string) string {
mime, err := mimetype.DetectFile(path)
if err != nil {
return ""
}
return mime.String()
}

View File

@ -13,6 +13,7 @@ export namespace File {
updateTime: string;
modTime: string;
mode: number;
mimeType: string;
items: File[];
}
@ -40,4 +41,12 @@ export namespace File {
path: string;
isDir: boolean;
}
export interface FileCompress {
files: string[];
type: string;
dst: string;
name: string;
replace: boolean;
}
}

View File

@ -18,5 +18,9 @@ export const DeleteFile = (form: File.FileDelete) => {
};
export const ChangeFileMode = (form: File.FileCreate) => {
return http.post<File.File>('files/mode', form);
return http.post<File.FileCreate>('files/mode', form);
};
export const CompressFile = (form: File.FileCompress) => {
return http.post<File.FileCompress>('files/compress', form);
};

View File

@ -24,7 +24,7 @@
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import { computed, ref, toRefs, watch, onMounted } from 'vue';
import { computed, ref, toRefs, watch, onUpdated } from 'vue';
interface Role {
r: boolean;
@ -152,7 +152,12 @@ const changeMode = (val: String) => {
getRoleNum(val[3], form.value.public);
};
onMounted(() => {
// onMounted(() => {
// form.value.mode = mode.value;
// changeMode(form.value.mode);
// });
onUpdated(() => {
form.value.mode = mode.value;
changeMode(form.value.mode);
});

View File

@ -0,0 +1,17 @@
export enum CompressType {
Zip = 'zip',
Gz = 'gz',
Bz2 = 'bz2',
Tar = 'tar',
TarGz = 'tarGz',
Xz = 'xz',
}
export enum CompressExtention {
zip = '.zip',
gz = '.gz',
bz2 = '.tar.bz2',
tar = '.tar',
tarGz = '.tar.gz',
xz = '.tar.xz',
}

View File

@ -151,4 +151,37 @@ export default {
request: 'request',
response: 'response',
},
file: {
dir: 'folder',
upload: 'Upload',
download: 'download',
fileName: 'file name',
search: 'find',
mode: 'permission',
owner: 'owner',
file: 'file',
remoteFile: 'remote download',
share: 'Share',
sync: 'Data synchronization',
size: 'size',
updateTime: 'Modification time',
open: 'open',
rename: 'rename',
role: 'authority',
info: 'Properties',
linkFile: 'soft link file',
terminal: 'terminal',
shareList: 'Share List',
zip: 'compress',
user: 'User',
group: 'user group',
path: 'path',
public: 'public',
setRole: 'Set permissions',
link: 'Whether to link',
rRole: 'read',
wRole: 'Write',
xRole: 'executable',
name: 'name',
},
};

View File

@ -33,6 +33,7 @@ export default {
sureLogOut: '您是否确认退出登录?',
createSuccess: '新建成功',
updateSuccess: '更新成功',
compressSuccess: '压缩成功',
},
login: {
captchaHelper: '请输入验证码',
@ -183,5 +184,11 @@ export default {
rRole: '读取',
wRole: '写入',
xRole: '可执行',
name: '名称',
compress: '压缩',
deCompress: '解压',
compressType: '压缩格式',
compressDst: '压缩路径',
replace: '覆盖已存在的文件',
},
};

View File

@ -24,12 +24,20 @@ import { ChangeFileMode } from '@/api/modules/files';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';
import FileRole from '@/components/file-role/index.vue';
interface Props {
open: boolean;
file: Object;
}
const props = withDefaults(defineProps<Props>(), {});
const props = defineProps({
open: {
type: Boolean,
default: false,
},
file: {
type: Object,
default: function () {
return {};
},
},
});
let form = ref<File.FileCreate>({ path: '', isDir: false, mode: 0o755 });
let loading = ref<Boolean>(false);
let mode = ref('0755');

View File

@ -0,0 +1,124 @@
<template>
<el-dialog v-model="open" :title="title" :before-close="handleClose" width="30%" @open="onOpen" v-loading="loading">
<el-form ref="fileForm" label-position="left" :model="form" label-width="100px" :rules="rules">
<el-form-item :label="$t('file.compressType')" prop="type">
<el-select v-model="form.type">
<el-option v-for="item in options" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item :label="$t('file.name')" prop="name">
<el-input v-model="form.name">
<template #append>{{ extension }}</template></el-input
>
</el-form-item>
<el-form-item :label="$t('file.compressDst')" prop="dst">
<el-input v-model="form.dst"></el-input>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.replace" :label="$t('file.replace')"></el-checkbox>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit(fileForm)">{{ $t('commons.button.confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import i18n from '@/lang';
import { computed, reactive, ref, toRefs } from 'vue';
import { File } from '@/api/interface/file';
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import { Rules } from '@/global/form-rues';
import { CompressExtention, CompressType } from '@/enums/files';
import { CompressFile } from '@/api/modules/files';
const props = defineProps({
open: {
type: Boolean,
default: false,
},
files: {
type: Array,
default: function () {
return [];
},
},
type: {
type: String,
default: 'compress',
},
dst: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
});
const rules = reactive<FormRules>({
type: [Rules.required],
dst: [Rules.required],
name: [Rules.required],
});
const { open, files, type, dst, name } = toRefs(props);
const fileForm = ref<FormInstance>();
let loading = ref(false);
let form = ref<File.FileCompress>({ files: [], type: 'zip', dst: '', name: '', replace: false });
let options = ref<string[]>([]);
const em = defineEmits(['close']);
const title = computed(() => {
return i18n.global.t('file.' + type.value);
});
const extension = computed(() => {
return CompressExtention[form.value.type];
});
const handleClose = () => {
em('close', open);
};
const onOpen = () => {
form.value = {
dst: dst.value,
type: 'zip',
files: files.value as string[],
name: name.value,
replace: false,
};
options.value = [];
for (const t in CompressType) {
options.value.push(CompressType[t]);
}
};
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (!valid) {
return;
}
let addItem = {};
Object.assign(addItem, form.value);
addItem['name'] = form.value.name + extension.value;
CompressFile(addItem as File.FileCompress)
.then(() => {
ElMessage.success(i18n.global.t('commons.msg.compressSuccess'));
handleClose();
})
.finally(() => {
loading.value = false;
});
});
};
</script>

View File

@ -8,8 +8,8 @@
v-loading="loading"
>
<el-form ref="fileForm" label-position="left" :model="form" label-width="100px" :rules="rules">
<el-form-item :label="$t('file.path')"> <el-input v-model="getPath" disabled /></el-form-item>
<el-form-item :label="$t('file.name')"> <el-input v-model="name" /></el-form-item>
<el-form-item :label="$t('file.path')" prop="path"> <el-input v-model="getPath" disabled /></el-form-item>
<el-form-item :label="$t('file.name')" prop="name"> <el-input v-model="form.name" /></el-form-item>
<el-checkbox v-model="isLink" :label="$t('file.link')"></el-checkbox>
</el-form>
<el-checkbox v-model="setRole" :label="$t('file.setRole')"></el-checkbox>
@ -36,15 +36,14 @@ const fileForm = ref<FormInstance>();
let loading = ref(false);
let setRole = ref(false);
let isLink = ref(false);
let name = ref('');
let path = ref('');
const props = defineProps({
open: Boolean,
file: Object,
});
const { open, file } = toRefs(props);
let form = ref<File.FileCreate>({ path: '', isDir: false, mode: 0o755 });
let addItem = ref<File.FileCreate>({ path: '', isDir: false, mode: 0o755 });
let form = ref({ name: '', path: '' });
const em = defineEmits(['close']);
const handleClose = () => {
em('close', open);
@ -52,14 +51,19 @@ const handleClose = () => {
const rules = reactive<FormRules>({
name: [Rules.required],
path: [Rules.required],
});
const getMode = (val: number) => {
form.value.mode = val;
addItem.value.mode = val;
};
let getPath = computed(() => {
return path.value + '/' + name.value;
if (form.value.path === '/') {
return form.value.path + form.value.name;
} else {
return form.value.path + '/' + form.value.name;
}
});
const submit = async (formEl: FormInstance | undefined) => {
@ -69,8 +73,8 @@ const submit = async (formEl: FormInstance | undefined) => {
return;
}
loading.value = true;
form.value.path = getPath.value;
CreateFile(form.value)
addItem.value.path = getPath.value;
CreateFile(addItem.value)
.then(() => {
ElMessage.success(i18n.global.t('commons.msg.createSuccess'));
handleClose();
@ -83,9 +87,9 @@ const submit = async (formEl: FormInstance | undefined) => {
const onOpen = () => {
const f = file?.value as File.FileCreate;
form.value.isDir = f.isDir;
addItem.value.isDir = f.isDir;
addItem.value.path = f.path;
form.value.name = '';
form.value.path = f.path;
path.value = f.path;
name.value = '';
};
</script>

View File

@ -1,5 +1,5 @@
<template>
<LayoutContent :header="$t('menu.files')">
<LayoutContent>
<el-row :gutter="20">
<el-col :span="5">
<el-scrollbar height="800px">
@ -98,6 +98,13 @@
</el-col>
<CreateFile :open="openCreate" :file="fileCreate" @close="closeCreate"></CreateFile>
<ChangeRole :open="openModePage" :file="modeForm" @close="closeMode"></ChangeRole>
<Compress
:open="compressPage.open"
:files="compressPage.files"
:dst="compressPage.dst"
:name="compressPage.name"
@close="closeCompress"
></Compress>
</el-row>
</LayoutContent>
</template>
@ -114,21 +121,24 @@ import BreadCrumbs from '@/components/bread-crumbs/index.vue';
import BreadCrumbItem from '@/components/bread-crumbs/bread-crumbs-item.vue';
import CreateFile from './create.vue';
import ChangeRole from './change-role.vue';
import Compress from './compress.vue';
import { useDeleteData } from '@/hooks/use-delete-data';
let data = ref();
let selects = ref<any>([]);
let req = reactive({ path: '/', expand: true });
let loading = ref<boolean>(false);
let treeLoading = ref<boolean>(false);
let loading = ref(false);
let treeLoading = ref(false);
let paths = ref<string[]>([]);
let fileTree = ref<File.FileTree[]>([]);
let expandKeys = ref<string[]>([]);
let openCreate = ref<boolean>(false);
let openCreate = ref(false);
let fileCreate = ref<File.FileCreate>({ path: '/', isDir: false, mode: 0o755 });
let openModePage = ref<boolean>(false);
let openModePage = ref(false);
let modeForm = ref<File.FileCreate>({ path: '/', isDir: false, mode: 0o755 });
let compressPage = reactive({ open: false, files: [''], name: '', dst: '' });
const defaultProps = {
children: 'children',
label: 'name',
@ -252,6 +262,17 @@ const closeMode = () => {
search(req);
};
const openCompress = (item: File.File) => {
compressPage.open = true;
compressPage.files = [item.path];
compressPage.name = item.name;
compressPage.dst = req.path;
};
const closeCompress = () => {
compressPage.open = false;
search(req);
};
onMounted(() => {
search(req);
});
@ -267,6 +288,7 @@ const buttons = [
},
{
label: i18n.global.t('file.zip'),
click: openCompress,
},
{
label: i18n.global.t('file.rename'),
@ -283,7 +305,6 @@ const buttons = [
<style>
.path {
margin-top: -50px;
height: 30px;
margin-bottom: 5px;
}

View File

@ -30,7 +30,8 @@
"@/*": ["src/*"]
},
//
"skipLibCheck": true
"skipLibCheck": true,
"suppressImplicitAnyIndexErrors": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.js"]