7 changed files with 811 additions and 1 deletions
@ -0,0 +1,58 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"aufs/db" |
|||
"aufs/util" |
|||
"encoding/json" |
|||
"fmt" |
|||
"net/http" |
|||
"strings" |
|||
) |
|||
|
|||
type Brespone struct { |
|||
Status string `json:"status"` |
|||
Data []db.StFileInfo `json:"data"` //目录下的文件
|
|||
} |
|||
|
|||
// 输出数据库中的基础文件的结构和hash
|
|||
func BfsInfo(w http.ResponseWriter, r *http.Request) { |
|||
// 监听的目录通过?p=的方式传入
|
|||
urlpath := r.URL.Query().Get("p") |
|||
fmt.Printf("your params:%s\n", urlpath) |
|||
// 防止逃逸,造成漏洞
|
|||
if strings.Contains(urlpath, "../") { |
|||
// urlpath = "Lg=="
|
|||
urlpath = util.Bas64end(".") |
|||
} |
|||
|
|||
// dsrpath := util.Base64dec(urlpath)
|
|||
// 如果根目录
|
|||
if urlpath == "" || urlpath == "." || urlpath == "Lg==" { |
|||
urlpath = util.Bas64end(".") |
|||
// urlpath = "Lg=="
|
|||
} |
|||
|
|||
fmt.Printf("after chk:%s\n", urlpath) |
|||
|
|||
// 链接数据库
|
|||
db.Init() |
|||
// 获取请求的信息
|
|||
flists := db.Fquery(urlpath) |
|||
// fmt.Printf("stfile :%v\n", flist)
|
|||
//
|
|||
bfslist := make([]db.StFileInfo, 0) |
|||
//
|
|||
for _, v := range flists { |
|||
bfslist = append(bfslist, v) |
|||
} |
|||
|
|||
// fmt.Fprintf(w, "%s:sqlite query ...", r.Host)
|
|||
response := Brespone{ |
|||
Status: "success", |
|||
Data: bfslist, |
|||
} |
|||
|
|||
// 开启跨域
|
|||
uCorsHadler(w, r) |
|||
json.NewEncoder(w).Encode(response) |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"aufs/config" |
|||
"aufs/db" |
|||
"aufs/util" |
|||
"encoding/json" |
|||
"fmt" |
|||
"net/http" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
) |
|||
|
|||
// json 结构体
|
|||
type Response struct { |
|||
Status string `json:"status"` //状态
|
|||
Data FilesListJson `json:"data"` //目录下的文件
|
|||
Curdir string `json:"curdir"` // 扫描的目录
|
|||
WorksDir string `json:"workdir"` //监听目录
|
|||
Hostip string `json:"hostip"` //运行的主机ip
|
|||
} |
|||
|
|||
// 文件输出的结构
|
|||
type FileJson struct { |
|||
Fname string `json:"fname"` |
|||
Dirflag bool `json:"dirflag"` |
|||
Isbackup int `json:"isbackup"` |
|||
Fhash string `json:"hash"` // hash
|
|||
Fsize string `json:"size"` //文件大小, 输出带单位的大小
|
|||
Frehash string `json:"rehash"` // 参考hash
|
|||
} |
|||
|
|||
type FilesListJson struct { |
|||
Flist []FileJson `json:"list"` |
|||
} |
|||
|
|||
// 获取运行的路径
|
|||
var Gpath string |
|||
|
|||
// 遍历监视目录,发送到json中
|
|||
func SerInfo(w http.ResponseWriter, r *http.Request) { |
|||
// 监听的目录通过?p=的方式传入
|
|||
urlpath := r.URL.Query().Get("p") |
|||
// 防止逃逸,造成漏洞
|
|||
if strings.Contains(urlpath, "../") || urlpath == "" { |
|||
urlpath = "." |
|||
} |
|||
|
|||
// urlpath 进行base64 解码
|
|||
dsrpath := util.Base64dec(urlpath) |
|||
// 监听的根目录
|
|||
realFilePath := filepath.Join(config.G.FilePath, dsrpath) |
|||
// 时间目录的情况
|
|||
fileInfo, err := os.Stat(realFilePath) |
|||
if err != nil { |
|||
http.Error(w, err.Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
// 链接数据库
|
|||
db.Init() |
|||
// 获取请求的信息
|
|||
rcflists := db.Fquery(util.Bas64end(dsrpath)) |
|||
//
|
|||
// list json
|
|||
var flist FilesListJson |
|||
//针对目录的情况才输出
|
|||
// todo 如果是文件的话 暂时不处理
|
|||
if fileInfo.IsDir() { |
|||
// 遍历目录
|
|||
files, err := os.ReadDir(realFilePath) |
|||
if err != nil { |
|||
http.Error(w, err.Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
// 遍历
|
|||
for _, v := range files { |
|||
// fmt.Printf("rang v:%v\n", v)
|
|||
isbak := 0 |
|||
rchash := "" //参考的hash
|
|||
// 如果有 backup
|
|||
if strings.Contains(v.Name(), "backup") { |
|||
isbak = 1 |
|||
} |
|||
// 如果是文件的话,就计算hash和大小
|
|||
if v.IsDir() { |
|||
//While entry is A Directory
|
|||
flist.Flist = append(flist.Flist, FileJson{Fname: v.Name(), Dirflag: v.IsDir(), Isbackup: isbak, Fhash: "", Fsize: "", Frehash: ""}) |
|||
} else { |
|||
// 计算文件的hash
|
|||
funame := filepath.Join(realFilePath, v.Name()) |
|||
fhash := util.CalacHash(funame) |
|||
//
|
|||
for _, av := range rcflists { |
|||
if av.Fname == v.Name() { |
|||
rchash = av.Fhash |
|||
} |
|||
} |
|||
// 文件大小
|
|||
// 获取文件大小(以字节为单位)
|
|||
sizeInBytes := fileInfo.Size() |
|||
sizeStr := fmt.Sprintf("%.2f KB", float64(sizeInBytes)/1024) |
|||
// output
|
|||
flist.Flist = append(flist.Flist, FileJson{Fname: v.Name(), Dirflag: v.IsDir(), Isbackup: isbak, Fhash: fhash, Fsize: sizeStr, Frehash: rchash}) |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
// respone file list
|
|||
response := Response{ |
|||
Status: "success", |
|||
Curdir: urlpath, |
|||
WorksDir: config.G.FilePath, |
|||
Hostip: config.G.LocalIP, |
|||
Data: flist, |
|||
} |
|||
|
|||
// 开启跨域
|
|||
uCorsHadler(w, r) |
|||
json.NewEncoder(w).Encode(response) |
|||
} |
|||
|
|||
// 跨域函数
|
|||
func uCorsHadler(w http.ResponseWriter, r *http.Request) { |
|||
// 设置跨域响应头
|
|||
w.Header().Set("Access-Control-Allow-Origin", "*") |
|||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS,PUT,DELETET") |
|||
// w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Accept,Accept-Length,Accept-Encoding,X-XSRF-TOKEN,X-XSRF-TOKEN")
|
|||
w.Header().Set("Access-Control-Allow-Headers", "*") |
|||
//
|
|||
w.Header().Set("Content-Type", "application/json") |
|||
|
|||
// 如果是OPTIONS请求,返回200 OK
|
|||
if r.Method == "OPTIONS" { |
|||
// fmt.Printf("options is now \n")
|
|||
// w.WriteHeader(http.StatusOK)
|
|||
return |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
package db |
|||
|
|||
// 定义数据库中用的模型
|
|||
type StFileInfo struct { |
|||
Id string `json:"id"` |
|||
Fpath string `json:"fpath"` |
|||
Fhash string `json:"fhash"` |
|||
Fname string `json:"fname"` |
|||
} |
|||
@ -0,0 +1,100 @@ |
|||
package db |
|||
|
|||
import ( |
|||
"fmt" |
|||
|
|||
// 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
|
|||
"github.com/jmoiron/sqlx" |
|||
_ "github.com/logoove/sqlite" |
|||
) |
|||
|
|||
var db *sqlx.DB |
|||
var err error |
|||
|
|||
func Init() { |
|||
// fmt.Printf("hey,I am initilize function in SqliteDb\n")s
|
|||
//
|
|||
// Open() 函数指定驱动名称和数据源名称
|
|||
db, err = sqlx.Open("sqlite", "ups.db") |
|||
if err != nil { |
|||
fmt.Printf("Database creation failed: %v\n", err) |
|||
return |
|||
} |
|||
// 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
|
|||
// defer db.Close()
|
|||
//
|
|||
connectDB() |
|||
} |
|||
|
|||
// 连接数据库
|
|||
func connectDB() { |
|||
var version string |
|||
// QueryRow() 执行查询,返回版本号
|
|||
err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version) |
|||
if err != nil { |
|||
fmt.Printf("Database creation failed: %v\n", err) |
|||
return |
|||
} |
|||
// 连接成功,打印出"database connected:版本号"
|
|||
fmt.Printf("Database creation successful: %v\n", version) |
|||
} |
|||
|
|||
// 创建数据库表
|
|||
func CreateTable() { |
|||
// 建表语句
|
|||
sts := ` |
|||
CREATE TABLE f_info ( |
|||
id INTEGER PRIMARY KEY NOT NULL, |
|||
fname TEXT NOT NULL, |
|||
fpath TEXT NOT NULL, |
|||
fhash TEXT NOT NULL |
|||
);` |
|||
|
|||
// 使用db.Exec() 函数来执行 SQL 语句
|
|||
_, err = db.Exec(sts) |
|||
if err != nil { |
|||
fmt.Printf("Failed to create database table: %v\n", err) |
|||
return |
|||
} |
|||
fmt.Printf("Successfully created database table! \n") |
|||
} |
|||
|
|||
// 插入数据
|
|||
func InsertStf(sf StFileInfo) { |
|||
// 插入语句
|
|||
res, err := db.Exec("INSERT INTO f_info(fname, fpath,fhash) VALUES(?,?,?)", sf.Fname, sf.Fpath, sf.Fhash) |
|||
if err != nil { |
|||
fmt.Printf("Insert data failed: %v\n", err) |
|||
return |
|||
} |
|||
|
|||
// 获取自增ID
|
|||
lastInsertId, _ := res.LastInsertId() |
|||
fmt.Printf("Successfully inserted data, lastInsertId = %v\n", lastInsertId) |
|||
} |
|||
|
|||
// 查询数据
|
|||
func Fquery(fpbs string) (stlist []StFileInfo) { |
|||
// 结果重量集合
|
|||
stlist = make([]StFileInfo, 0) |
|||
|
|||
// 查询语句
|
|||
rows, err := db.Query("SELECT id,fname,fpath,fhash FROM f_info WHERE fpbs = ?", fpbs) |
|||
//
|
|||
if err != nil { |
|||
fmt.Printf("Failed to query data: %v\n", err) |
|||
return |
|||
} |
|||
// FOR loop
|
|||
for rows.Next() { |
|||
// var weight float64
|
|||
var st StFileInfo |
|||
err = rows.Scan(&st.Id, &st.Fname, &st.Fpath, &st.Fhash) |
|||
if err != nil { |
|||
fmt.Printf("Failed to read data: %v\n", err) |
|||
continue |
|||
} |
|||
stlist = append(stlist, st) |
|||
} |
|||
return stlist |
|||
} |
|||
@ -1,3 +1,29 @@ |
|||
module aufs |
|||
|
|||
go 1.22.1 |
|||
go 1.23.0 |
|||
|
|||
toolchain go1.24.6 |
|||
|
|||
require ( |
|||
github.com/jmoiron/sqlx v1.4.0 |
|||
github.com/logoove/sqlite v1.37.1 |
|||
github.com/schollz/progressbar/v3 v3.18.0 |
|||
google.golang.org/protobuf v1.36.7 |
|||
) |
|||
|
|||
require ( |
|||
github.com/dustin/go-humanize v1.0.1 // indirect |
|||
github.com/google/uuid v1.6.0 // indirect |
|||
github.com/mattn/go-isatty v0.0.20 // indirect |
|||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect |
|||
github.com/ncruces/go-strftime v0.1.9 // indirect |
|||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect |
|||
github.com/rivo/uniseg v0.4.7 // indirect |
|||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect |
|||
golang.org/x/sys v0.34.0 // indirect |
|||
golang.org/x/term v0.28.0 // indirect |
|||
modernc.org/libc v1.66.3 // indirect |
|||
modernc.org/mathutil v1.7.1 // indirect |
|||
modernc.org/memory v1.11.0 // indirect |
|||
modernc.org/sqlite v1.38.2 // indirect |
|||
) |
|||
|
|||
@ -0,0 +1,85 @@ |
|||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= |
|||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= |
|||
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= |
|||
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= |
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= |
|||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= |
|||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= |
|||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= |
|||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= |
|||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= |
|||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= |
|||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= |
|||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= |
|||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= |
|||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= |
|||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= |
|||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= |
|||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= |
|||
github.com/logoove/sqlite v1.37.1 h1:smJKG1VTnFdkxLWLeeh7Sy+xvK6yYg+u7dXutj9c7LM= |
|||
github.com/logoove/sqlite v1.37.1/go.mod h1:fLu3SyDziw8V0K6THYj0jTk6Z+VBbRIoK843CglTWME= |
|||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= |
|||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= |
|||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= |
|||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= |
|||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= |
|||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= |
|||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= |
|||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= |
|||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= |
|||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= |
|||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
|||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= |
|||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= |
|||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= |
|||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= |
|||
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= |
|||
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= |
|||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= |
|||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= |
|||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= |
|||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= |
|||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= |
|||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= |
|||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= |
|||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= |
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= |
|||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= |
|||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= |
|||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= |
|||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= |
|||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= |
|||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= |
|||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= |
|||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|||
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= |
|||
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= |
|||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= |
|||
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= |
|||
modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= |
|||
modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= |
|||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= |
|||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= |
|||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= |
|||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= |
|||
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= |
|||
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= |
|||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= |
|||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= |
|||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= |
|||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= |
|||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= |
|||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= |
|||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= |
|||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= |
|||
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= |
|||
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= |
|||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= |
|||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= |
|||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= |
|||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= |
|||
@ -0,0 +1,391 @@ |
|||
package util |
|||
|
|||
import ( |
|||
"archive/zip" |
|||
"aufs/config" |
|||
"bytes" |
|||
"crypto/sha256" |
|||
"encoding/base64" |
|||
"fmt" |
|||
"io" |
|||
"mime/multipart" |
|||
"net/http" |
|||
"os" |
|||
"path" |
|||
"path/filepath" |
|||
"strings" |
|||
|
|||
"github.com/schollz/progressbar/v3" |
|||
) |
|||
|
|||
// 遍历目录下的文件
|
|||
// 是否只扫相对路径下
|
|||
func GetDirFilePaths(dirPath string, relativeOnly bool) ([]string, error) { |
|||
var filePaths []string |
|||
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if !info.IsDir() { |
|||
if relativeOnly { |
|||
fileName := filepath.Base(path) |
|||
relativePath := filepath.ToSlash(filepath.Join(filepath.Base(dirPath), fileName)) |
|||
filePaths = append(filePaths, relativePath) |
|||
} else { |
|||
filePaths = append(filePaths, filepath.ToSlash(path)) |
|||
} |
|||
} |
|||
return nil |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
return filePaths, nil |
|||
} |
|||
|
|||
// base64 encode
|
|||
// url safe
|
|||
func Bas64end(str string) string { |
|||
// bdata:=
|
|||
return base64.URLEncoding.EncodeToString([]byte(str)) |
|||
} |
|||
|
|||
// base64 url safe uneconde
|
|||
func Base64dec(bsstr string) string { |
|||
dedc, _ := base64.URLEncoding.DecodeString(bsstr) |
|||
return string(dedc) |
|||
} |
|||
|
|||
// 计算文件的hash
|
|||
func CalacHash(rfile string) string { |
|||
// 获取到真实地址
|
|||
//
|
|||
file, err := os.Open(rfile) |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
defer file.Close() |
|||
|
|||
// initlize hash object
|
|||
hash := sha256.New() |
|||
|
|||
// write file into hash object
|
|||
if _, err := io.Copy(hash, file); err != nil { |
|||
panic(err) |
|||
} |
|||
// get hash value
|
|||
hashBytes := hash.Sum(nil) |
|||
//converto to hash string
|
|||
hastString := fmt.Sprintf("%x", hashBytes) |
|||
return hastString |
|||
} |
|||
|
|||
// 判断文件是否存在
|
|||
func IsFileExist(filename string) bool { |
|||
if _, err := os.Stat(filename); err == nil { |
|||
return true |
|||
} |
|||
return false |
|||
} |
|||
|
|||
// 发送文件
|
|||
func SendFiles(filePath string, url string) error { |
|||
filePath = filepath.ToSlash(filePath) |
|||
fileInfo, err := os.Stat(filePath) |
|||
if err != nil { |
|||
if os.IsNotExist(err) { |
|||
return fmt.Errorf("file [%s] not exist", filePath) |
|||
} |
|||
return fmt.Errorf("file [%s] error: %w", filePath, err) |
|||
} |
|||
|
|||
if fileInfo.IsDir() { |
|||
return postDirectory(filePath, url) |
|||
} |
|||
|
|||
return postFile(filePath, path.Base(filePath), url) |
|||
} |
|||
|
|||
// 传送文件夹
|
|||
func postDirectory(dirPath string, url string) error { |
|||
files, err := GetDirFilePaths(dirPath, false) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
fmt.Println("\nAll files in folder:") |
|||
for _, file := range files { |
|||
fmt.Println(file) |
|||
} |
|||
|
|||
var confirm string |
|||
fmt.Print("\nTransfer all files? [Y/N] ") |
|||
fmt.Scanln(&confirm) |
|||
if strings.ToLower(confirm) != "y" { |
|||
fmt.Print("\nCancel send all files ") |
|||
return nil |
|||
} |
|||
|
|||
for _, file := range files { |
|||
fileName, _ := filepath.Rel(dirPath, file) |
|||
fileName = filepath.Join(filepath.Base(dirPath), fileName) |
|||
err := postFile(file, fileName, url) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
} |
|||
fmt.Printf("Send folder %s success.\n", dirPath) |
|||
return nil |
|||
} |
|||
|
|||
// 传送文件
|
|||
func postFile(wfpath string, filename string, url string) error { |
|||
payload := &bytes.Buffer{} |
|||
writer := multipart.NewWriter(payload) |
|||
|
|||
file, err := os.Open(wfpath) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer file.Close() |
|||
|
|||
part, err := writer.CreateFormFile("file", filepath.ToSlash(filename)) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
fileInfo, _ := file.Stat() |
|||
bar := progressbar.DefaultBytes( |
|||
fileInfo.Size(), |
|||
fmt.Sprintf("Uploading [%s]", filename), |
|||
) |
|||
|
|||
_, err = io.Copy(io.MultiWriter(part, bar), file) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
err = writer.Close() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
req, err := http.NewRequest(http.MethodPost, url, payload) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
req.Header.Set("Content-Type", writer.FormDataContentType()) |
|||
// 在头里面加上路径,去除前缀
|
|||
rlpath := strings.TrimPrefix(wfpath, config.G.FilePath) |
|||
// fmt.Printf("wfpath:%s,rel path is:%s", wfpath, rlpath)
|
|||
req.Header.Set("Fpath", Bas64end(rlpath)) |
|||
|
|||
client := &http.Client{} |
|||
resp, err := client.Do(req) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer resp.Body.Close() |
|||
|
|||
if resp.StatusCode != http.StatusOK { |
|||
return fmt.Errorf("upload failed with status code: %d", resp.StatusCode) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
/* |
|||
* add file to zip |
|||
*/ |
|||
func ZipFiles(zipname string, files []string, zippath string) error { |
|||
fmt.Printf("zipname:%s\n", zipname) |
|||
// 创建zip文件
|
|||
newZipFile, err := os.Create(zipname) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
defer newZipFile.Close() |
|||
// zip写头
|
|||
zipWriter := zip.NewWriter(newZipFile) |
|||
defer zipWriter.Close() |
|||
|
|||
// 把files添加到zip中
|
|||
for _, file := range files { |
|||
//
|
|||
fmt.Printf("zipfiles in function :%s\n", file) |
|||
|
|||
//
|
|||
zipfile, err := os.Open(file) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer zipfile.Close() |
|||
|
|||
//
|
|||
info, err := zipfile.Stat() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
//
|
|||
header, err := zip.FileInfoHeader(info) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
// 在zip存档中设置文件的相对路径
|
|||
header.Name, err = filepath.Rel(filepath.Dir(config.G.FilePath), file) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
// 转换为Unix风格的路径分隔符
|
|||
header.Name = filepath.ToSlash(header.Name) |
|||
// 目录需要拼上一个 "/" ,否则会出现一个和目录一样的文件在压缩包中
|
|||
if info.IsDir() { |
|||
header.Name += "/" |
|||
} else { |
|||
// 将压缩方法设置为deflate
|
|||
header.Method = zip.Deflate |
|||
} |
|||
//
|
|||
fmt.Printf("header.name is %s\n", header.Name) |
|||
|
|||
writer, err := zipWriter.CreateHeader(header) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
if _, err = io.Copy(writer, zipfile); err != nil { |
|||
return err |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
// 解压缩zip文件
|
|||
// 这个方法必须是首字母大写的,才能被注册
|
|||
// src: 需要解压的zip文件
|
|||
func DecompressZip(zpFname string) error { |
|||
// 下载文件
|
|||
archive, err := zip.OpenReader(zpFname) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
// 取zip文件的绝对路径的文件夹。会默认解压到files下,暂停使用
|
|||
// dir := filepath.Dir(zpFname)
|
|||
defer archive.Close() |
|||
// 遍历目录
|
|||
for _, f := range archive.File { |
|||
// zip 解压的时候,路径为监听的路径
|
|||
filePath := filepath.Join(config.G.FilePath, f.Name) |
|||
// 暂停原因 屏蔽解压到files 目录下
|
|||
//filePath := filepath.Join(dir, f.Name)
|
|||
if f.FileInfo().IsDir() { |
|||
os.MkdirAll(filePath, os.ModePerm) |
|||
continue |
|||
} |
|||
// 父文件夹开始创建目录
|
|||
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { |
|||
return fmt.Errorf("failed to make directory (%v)", err) |
|||
} |
|||
// 文件原有模式
|
|||
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) |
|||
if err != nil { |
|||
return fmt.Errorf("failed to create file (%v)", err) |
|||
} |
|||
fileInArchive, err := f.Open() |
|||
if err != nil { |
|||
return fmt.Errorf("failed to open file in zip (%v)", err) |
|||
} |
|||
if _, err := io.Copy(dstFile, fileInArchive); err != nil { |
|||
return fmt.Errorf("failed to copy file in zip (%v)", err) |
|||
} |
|||
dstFile.Close() |
|||
fileInArchive.Close() |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
// dest:目的地址以及压缩文件名 eg:/data/logZip/2022-12-12-log.zip
|
|||
// paths:需要压缩的所有文件所组成的集合
|
|||
func CompressToZip(dest string, currentPath string, paths []string) error { |
|||
// fmt.Println("real path", currentPath)
|
|||
// 打开files 目录
|
|||
filesPath := "" |
|||
if dir, err := os.Getwd(); err == nil { |
|||
filesPath = dir + "/sync_zips/" |
|||
} |
|||
if err := os.MkdirAll(filesPath, os.ModePerm); err != nil { |
|||
fmt.Println(err.Error()) |
|||
} |
|||
// ToSlash 过滤windows的斜杠引起的bug
|
|||
zfile, err := os.Create(path.Join("./sync_zips", "/", dest)) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer zfile.Close() |
|||
zipWriter := zip.NewWriter(zfile) |
|||
defer zipWriter.Close() |
|||
|
|||
// 遍历带压缩的目录信息
|
|||
for _, src := range paths { |
|||
// 替换文件名,并且去除前后 "\" 或 "/"
|
|||
// path = strings.Trim(path, string(filepath.Separator))
|
|||
// 从配置中读取到源目录
|
|||
src = path.Join(currentPath, "/", src) |
|||
// 删除尾随路径(如果它是目录)
|
|||
src := strings.TrimSuffix(src, string(os.PathSeparator)) |
|||
// 文件遍历
|
|||
err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error { |
|||
if err != nil { |
|||
return err |
|||
} |
|||
// 创建本地文件头
|
|||
header, err := zip.FileInfoHeader(info) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
// 监听的工作目录作为文件的结尾,然后取相对路径
|
|||
// 在zip存档中设置文件的相对路径
|
|||
header.Name, err = filepath.Rel(filepath.Dir(config.G.FilePath), path) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
// 转换为Unix风格的路径分隔符
|
|||
header.Name = filepath.ToSlash(header.Name) |
|||
|
|||
// 目录需要拼上一个 "/" ,否则会出现一个和目录一样的文件在压缩包中
|
|||
if info.IsDir() { |
|||
header.Name += "/" |
|||
} else { |
|||
// 将压缩方法设置为deflate
|
|||
header.Method = zip.Deflate |
|||
} |
|||
// fmt.Printf("zip header:%v\n", header.Name)
|
|||
// 创建写入头的writer
|
|||
headerWriter, err := zipWriter.CreateHeader(header) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if info.IsDir() { |
|||
return nil |
|||
} |
|||
f, err := os.Open(path) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer f.Close() |
|||
_, err = io.Copy(headerWriter, f) |
|||
return err |
|||
}) |
|||
|
|||
if err != nil { |
|||
return err |
|||
} |
|||
} |
|||
// 存到指定位置
|
|||
os.Rename(dest, path.Join("./sync_zips/", dest)) |
|||
return nil |
|||
} |
|||
Loading…
Reference in new issue