Browse Source

增加文件发送

master
453530270@qq.com 1 year ago
parent
commit
95c44910c2
  1. 102
      fss/core/sendzip.go
  2. 43
      fss/fsw/index.html
  3. 4
      fss/go.mod
  4. 15
      fss/go.sum
  5. 4
      fss/main.go
  6. 113
      fss/util/fsutil.go

102
fss/core/sendzip.go

@ -0,0 +1,102 @@
package core
import (
"fmt"
"fss/config"
"fss/util"
"net"
"net/http"
"path"
"path/filepath"
"strings"
"time"
)
func SendZip(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
// 选择文件,并生成zip包
// 文件
zipfarr := r.Form["zipfiles"]
// 服务器ip地址
serip := r.Form["serverip"]
if serip[0] == "" {
http.Error(w, "remote server ip is blank!", http.StatusInternalServerError)
return
}
tpath := ""
// 选中的路径,可以为空
wtculpath := r.Form["curpath"]
if wtculpath != nil {
tpath = wtculpath[0]
}
// 实际路径
realFilePath := filepath.Join(config.G.FilePath, tpath)
// zip 文件名
zpFileName := "BIU_" + time.Now().Format("20060102_150405") + ".zip"
// 创建zip 异步?
taskId := make(chan string)
go func() {
util.CompressToZip(zpFileName, realFilePath, zipfarr)
taskId <- "arcok"
// fmt.Fprintln(w, "create archive:", err)
}()
// go util.CompressToZip(zpFileName, realFilePath, zipfarr)
fmt.Println("archive is createding...")
// 当前运行的目录
// ZIP 文件的实际路径
ziprl := path.Join("./files/", zpFileName)
// zip 创建成功后
rest := <-taskId
// 有压缩包 才可以操作
if strings.EqualFold(strings.ToLower(rest), "arcok") {
fmt.Println("archive is sending...")
// 创建udp 渠道发送数据
message := fmt.Sprintf("%s%s%s", config.G.DeviceName, "|", "sender")
UdpSendFile(serip[0], ziprl, zpFileName, message, w)
} else {
fmt.Println("archive is not exist!!!")
}
// 执行完 跳转到 首页
http.Redirect(w, r, "/console", http.StatusFound)
}
// udp 模式发送文件
/*
* serip 服务器ip,
* absfilepath 发送文件的时间路径,
* fname 文件名
* message 携带部分信息的消息
* http.ResponseWriter
*/
func UdpSendFile(serip string, absfilepath string, fname string, message string, w http.ResponseWriter) {
// 1、获取udp addr
remoteAddr, err := net.ResolveUDPAddr("udp", serip+":9099")
if err != nil {
return
}
// 2、 监听端口
conn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
return
}
defer conn.Close()
// 3、在端口发送数据
//message := fmt.Sprintf("%s%s%s", config.G.DeviceName, "|", "sender")
// 向链接通道发送数据 数据包头
conn.Write([]byte(message))
// 发送文件
go func() {
err := util.SendFiles(absfilepath, fmt.Sprintf("http://%s", remoteAddr))
if err != nil {
fmt.Printf("Send file to %s error: %s\n", remoteAddr, err)
}
}()
}

43
fss/fsw/index.html

@ -114,13 +114,15 @@
<p>监听目录:<span class="sc01"></span></p>
<p>相对目录: <span class="sc02"></span> </p>
<div class="col-md-12">
<a href="javascript:void(0);" class="btn btn-success btn-sm" id="slall">全选</a>
<a href="javascript:void(0);" class="btn btn-info btn-sm" id="sybtn">同步</a>
<a href="javascript:void(0);" class="btn btn-success btn-sm" id="slall" data-st="ss">全选</a>
<a href="javascript:void(0);" class="btn btn-info btn-sm" id="sybtn" data-st="ss">同步</a>
</div>
</div>
<!-- List group -->
<ul class="list-group" id="scsc"></ul>
<form action="/sendZip" method="post" class="ssform">
<ul class="list-group" id="scsc"></ul>
</form>
</div>
</div>
@ -198,7 +200,7 @@
}
// click function SOURCE SERVER
$("#entsip").on("click", function () {
scfs();
scfs("ss");
})
@ -225,7 +227,7 @@
$("#ssip").text("源站(" + scip + ")");
// 获取信息
gescinfo("#scsc", scip, urlpath);
gescinfo("#scsc", scip, urlpath,st);
//
$("#rstatus").append(html);
@ -234,32 +236,26 @@
// button click function for TARGET SERVER
$("#tentsip").on("click", function () {
$("#mbip").text("目标站(" + scip + ")");
tgfs();
tgfs("tg");
})
// 目标服务器的文件信息
var tgfs = function () {
var tgfs = function (st) {
tsip = $("input[name='tsip']").val();
// ip storage
sessionStorage.setItem("tscip", tsip);
//监视目录
// var jsdir = $("input[name='tsdir']").val();
// if (urlpath != '') {
// urlpath = encodeURIComponent(btoa(jsdir));
// }
//
var html = "<li class=\"list-group-item\">输入目标服务器" + tsip + "</li>";
// 目标站
$("#mbip").text("目标站(" + tsip + ")");
// 获取信息
gescinfo("#tgsc", tsip, urlpath);
gescinfo("#tgsc", tsip, urlpath,st);
//
$("#rstatus").append(html);
}
// 获取目标服务器的信息
var gescinfo = function (elemnt, scip, upath) {
var gescinfo = function (elemnt, scip, upath,st) {
upath = upath.replace("/\\/g", "\/");
// 客户端的状态地址
var url = "http://" + scip + ":9099/sc?p=" + upath;
@ -283,7 +279,7 @@
//
html += "<li class=\"list-group-item optzone " + chgflag + "\"><div class=\"col-md-10\">";
html += "<input type=\"checkbox\" class=\"mfile\" name=\"sfiles[]\" value=" + v.fname + " />";
html += "<input type=\"checkbox\" class="+st+'mfile'+" name=\"sfiles[]\" value=" + v.fname + " />";
if (v.dirflag) { //如果是文件夹
html += "<span class=\"icon folder-icon\"></span>" ;
html += v.fname
@ -342,15 +338,13 @@
//全选按钮设置点击事件
$("#slall").click(function () {
let st = $(this).data("st");
//1、循环设置其它多选框选中状态,跟标识用的变量一样
$(".mfile").prop("checked", chkall);
$("."+st+"mfile").prop("checked", chkall);
// down button toggle
if (chkall || chknum > 2) {
chknum += 1
} else {
chknum -= 1
}
//2、标识的变量取反
@ -359,9 +353,14 @@
//同步操作
$("#sybtn").on("click", function () {
// var st = $(this).data("st")
$(".ssform").submit();
// var ss = $("."+st+"mfile").hasClass("checked").val()
// console.log(ss)
// 获取选中的文件 或者文件夹
chkarr.push($("input[name='sfiles[]']:checked").val());
console.log(chkarr)
// chkarr.push($("input[name='sfiles[]']:checked").val());
// console.log(chkarr)
// var ss = $("input[name='sfiles[]']:checked").val();
//var ss = $(".mfile").has("checked").val()
// console.log(ss)

4
fss/go.mod

@ -5,6 +5,7 @@ go 1.22.1
require (
github.com/jmoiron/sqlx v1.4.0
github.com/logoove/sqlite v1.16.1
github.com/schollz/progressbar/v3 v3.14.6
)
require (
@ -12,10 +13,13 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // 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/mod v0.16.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/tools v0.19.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.41.0 // indirect

15
fss/go.sum

@ -1,5 +1,8 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@ -10,6 +13,7 @@ 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/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
@ -20,12 +24,21 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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.14.6 h1:GyjwcWBAf+GFDMLziwerKvpuS7ZF+mNTAXIB2aspiZs=
github.com/schollz/progressbar/v3 v3.14.6/go.mod h1:Nrzpuw3Nl0srLY0VlTvC4V6RL50pcEymjy6qyJAaLa0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
@ -33,6 +46,8 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=

4
fss/main.go

@ -19,6 +19,10 @@ func startWeb() {
http.HandleFunc("/sc", core.SerInfo)
// 数据库基础信息
http.HandleFunc("/bs", core.BfsInfo)
// 文件接收
http.HandleFunc("/rc", core.ReceiveHandler)
// 发送zip文件
http.HandleFunc("/sendZip", core.SendZip)
fmt.Printf("Starting server at port 9099\n")
// 启动HTTP服务器并监听端口 80,如果出现错误,则打印错误信息并退出

113
fss/util/fsutil.go

@ -2,13 +2,20 @@ package util
import (
"archive/zip"
"bytes"
"crypto/sha256"
"encoding/base64"
"fmt"
"fss/config"
"io"
"mime/multipart"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"github.com/schollz/progressbar/v3"
)
// 遍历目录下的文件
@ -81,6 +88,112 @@ func IsFileExist(filename string) bool {
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
*/

Loading…
Cancel
Save