package handler import ( "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) // 拼装, 文件的实际地址 ziprl := filepath.Join(bbpath, "/", bfile) // 1、获取udp addr remoteAddr, err := net.ResolveUDPAddr("udp", serip[0]+":9099") if err != nil { fmt.Printf("Failed to resolve %s: %v\n", serip[0], err) return } // 2、 监听端口 conn, err := net.DialUDP("udp", nil, remoteAddr) if err != nil { fmt.Printf("Failed to dial %s: %v\n", serip[0], err) return } defer conn.Close() // 3、在端口发送数据 message := fmt.Sprintf("%s%s%s", config.G.DeviceName, "|", "sender") // 向链接通道发送数据 数据包头 conn.Write([]byte(message)) // 发送文件 go func() { err := transfer.SendFiles(ziprl, fmt.Sprintf("http://%s", remoteAddr)) if err != nil { fmt.Printf("Send file to %s error: %s\n", remoteAddr, err) } }() // 页面上显示 fmt.Fprintf(w, "File:%s\\/%s,been sent successfully.", sbfile, sbpath) fmt.Fprintf(w, "deubg.....") } // 文件服务 func FileServerHandler(w http.ResponseWriter, r *http.Request) { currentPath := config.G.FilePath fileInfo, err := os.Stat(currentPath) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } basePath := filepath.Base(currentPath) if fileInfo.IsDir() { path := r.URL.Path[len("/download/"+basePath):] fullPath := filepath.Join(currentPath, path) http.ServeFile(w, r, fullPath) } else { http.ServeFile(w, r, currentPath) } } // 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 渠道发送数据 // 1、获取udp addr remoteAddr, err := net.ResolveUDPAddr("udp", serip[0]+":9099") if err != nil { fmt.Printf("Failed to resolve %s: %v\n", serip[0], err) return } // 2、 监听端口 conn, err := net.DialUDP("udp", nil, remoteAddr) if err != nil { fmt.Printf("Failed to dial %s: %v\n", serip[0], err) return } defer conn.Close() // 3、在端口发送数据 message := fmt.Sprintf("%s%s%s", config.G.DeviceName, "|", "sender") // 向链接通道发送数据 数据包头 conn.Write([]byte(message)) // 发送文件 go func() { err := transfer.SendFiles(ziprl, fmt.Sprintf("http://%s", remoteAddr)) if err != nil { fmt.Printf("Send file to %s error: %s\n", remoteAddr, err) } }() // 页面上显示 fmt.Fprintf(w, "File:%s,been sent successfully.", zpFileName) } else { fmt.Println("archive is not exist!!!") } } // 发送拦截 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) } }