You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
7.2 KiB
305 lines
7.2 KiB
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"net"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"fssc/config"
|
|
"fssc/internal/transfer"
|
|
"fssc/internal/util"
|
|
"fssc/web"
|
|
)
|
|
|
|
// rpc功能 压缩包的结构体
|
|
// 文件路径 文件名
|
|
type Args struct {
|
|
Zpfile, Fname string
|
|
}
|
|
|
|
// 获取文件大小的接口
|
|
type Size interface {
|
|
Size() int64
|
|
}
|
|
|
|
// 获取文件信息的接口
|
|
type Stat interface {
|
|
Stat() (os.FileInfo, error)
|
|
}
|
|
|
|
// 显示状态
|
|
func ReceiveStatus(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
// 显示当前传送文件的大小
|
|
case http.MethodPost:
|
|
file, _, err := r.FormFile("file")
|
|
if err != nil {
|
|
http.Error(w, err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
if statInterface, ok := file.(Stat); ok {
|
|
fileInfo, _ := statInterface.Stat()
|
|
fmt.Fprintf(w, "上传文件的大小为: %d", fileInfo.Size())
|
|
}
|
|
|
|
if sizeInterface, ok := file.(Size); ok {
|
|
fmt.Fprintf(w, "上传文件的大小为: %d", sizeInterface.Size())
|
|
}
|
|
return
|
|
}
|
|
|
|
// fmt.Fprintf(w, r.Method)
|
|
}
|
|
|
|
/**
|
|
** 文件更新服务器
|
|
**/
|
|
func UpServer(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
// 解析url中传递来的参数
|
|
fname := r.URL.Query().Get("f")
|
|
// 路径
|
|
fpath := r.URL.Query().Get("p")
|
|
|
|
// 文件列表模板
|
|
data := struct {
|
|
Bpath string
|
|
Bfile string
|
|
}{
|
|
Bpath: fpath,
|
|
Bfile: fname,
|
|
}
|
|
// 文件列表模板
|
|
tmpl, err := template.New("up").Parse(web.UpPage)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
err = tmpl.Execute(w, data)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
|
|
default:
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
|
|
}
|
|
|
|
// 处理单文件同步
|
|
func Supfile(w http.ResponseWriter, r *http.Request) {
|
|
r.ParseForm()
|
|
// loop
|
|
// for k, v := range r.Form {
|
|
// fmt.Println("key:%s,value:%s", k, v)
|
|
// }
|
|
|
|
// 服务器ip地址
|
|
serip := r.Form["sip"]
|
|
if serip[0] == "" {
|
|
http.Error(w, "remote server ip is blank!", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
// 文件名
|
|
sbfile := r.Form["bfile"]
|
|
// 文件路径
|
|
sbpath := r.Form["bpath"]
|
|
// 需要对他们进行base64解码
|
|
bpath := util.Base64dec(sbpath[0])
|
|
bfile := util.Base64dec(sbfile[0])
|
|
// 替换 反斜杠
|
|
//bbpath := strings.Replace(bpath, "\\", "/", -1)
|
|
bbpath := ""
|
|
// 判断是否为空
|
|
if bpath == "" {
|
|
// fmt.Printf("shit,it's blank path!!\n")
|
|
bbpath = "."
|
|
} else {
|
|
bbpath = filepath.ToSlash(bpath)
|
|
}
|
|
|
|
// fmt.Printf("rel path:%s - %s", bbpath, bfile)
|
|
//replacedPath := strings.ReplaceAll(path, "\\", "/")
|
|
// 拼装, 文件的实际地址
|
|
ziprl := filepath.Join(config.G.FilePath, "/", bbpath, "/", bfile)
|
|
// 创建udp 渠道发送数据
|
|
message := fmt.Sprintf("%s%s%s", "xdml|", bbpath, "|sender")
|
|
UdpSendFile(serip[0], ziprl, bfile, message, w)
|
|
// 执行完 跳转到 首页
|
|
http.Redirect(w, r, "/", http.StatusFound)
|
|
}
|
|
|
|
// udp 方式发送zip文件
|
|
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, "/", http.StatusFound)
|
|
}
|
|
|
|
// 发送拦截
|
|
func SendHandler(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
// serve download page for send
|
|
realFilePath := filepath.Join(config.G.FilePath, r.URL.Path[1:])
|
|
downloadPath := filepath.Join(filepath.Base(config.G.FilePath), r.URL.Path[1:])
|
|
fileInfo, err := os.Stat(realFilePath)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
data := struct {
|
|
DeviceName string
|
|
Rundir string
|
|
IsDir bool
|
|
FileName string
|
|
DownloadPath string
|
|
UrlPath string
|
|
Files []os.DirEntry
|
|
}{
|
|
DeviceName: config.G.DeviceName,
|
|
Rundir: config.G.FilePath,
|
|
DownloadPath: downloadPath,
|
|
UrlPath: strings.TrimSuffix(r.URL.Path, "/"),
|
|
//UrlPath: r.URL.Path,
|
|
}
|
|
|
|
if fileInfo.IsDir() {
|
|
data.IsDir = true
|
|
// 遍历目录
|
|
files, err := os.ReadDir(realFilePath)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
data.Files = files
|
|
} else {
|
|
data.FileName = filepath.Base(realFilePath)
|
|
}
|
|
|
|
// add self template function
|
|
fmap := template.FuncMap{"b64en": util.Bas64end}
|
|
// 文件列表模板
|
|
tmpl, err := template.New("list").Funcs(fmap).Parse(web.ListPage)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
err = tmpl.Execute(w, data)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
|
|
default:
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
}
|
|
|
|
// // 定义错误返回的json
|
|
type ErrJson struct {
|
|
Msg string `json:"message"`
|
|
}
|
|
|
|
// 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 {
|
|
mstr := fmt.Sprintf("Failed to resolve %s:%v", serip, err)
|
|
erjson := ErrJson{mstr}
|
|
outmsg, _ := json.Marshal(erjson)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(outmsg)
|
|
return
|
|
}
|
|
// 2、 监听端口
|
|
conn, err := net.DialUDP("udp", nil, remoteAddr)
|
|
if err != nil {
|
|
ustr := fmt.Sprintf("Failed to dial %s: %v", serip, err)
|
|
erjson := ErrJson{ustr}
|
|
outmsg, _ := json.Marshal(erjson)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(outmsg)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
// 3、在端口发送数据
|
|
//message := fmt.Sprintf("%s%s%s", config.G.DeviceName, "|", "sender")
|
|
// 向链接通道发送数据 数据包头
|
|
conn.Write([]byte(message))
|
|
// 发送文件
|
|
go func() {
|
|
err := transfer.SendFiles(absfilepath, fmt.Sprintf("http://%s", remoteAddr))
|
|
if err != nil {
|
|
fmt.Printf("Send file to %s error: %s\n", remoteAddr, err)
|
|
}
|
|
}()
|
|
}
|
|
|