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.
271 lines
6.6 KiB
271 lines
6.6 KiB
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
"mime"
|
|
"strings"
|
|
"time"
|
|
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"xtcfs/config"
|
|
"xtcfs/util"
|
|
|
|
"github.com/chyok/st/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 ReceiveHandler(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
// serve upload page for receive
|
|
// tmpl, err := template.New("index").Parse(web.UploadPage)
|
|
// if err != nil {
|
|
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
// // 获取当前设备名称
|
|
// err = tmpl.Execute(w, config.G.DeviceName)
|
|
// if err != nil {
|
|
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
// }
|
|
//
|
|
fmt.Fprintf(w, "%s:接收文件中...", r.Host)
|
|
case http.MethodPost:
|
|
// receive file and save
|
|
file, header, err := r.FormFile("file")
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
_, params, err := mime.ParseMediaType(header.Header.Get("Content-Disposition"))
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
filename := filepath.FromSlash(params["filename"])
|
|
|
|
// fpath
|
|
bfpath := r.Header.Get("Fpath")
|
|
|
|
//debug
|
|
// fmt.Printf("header params:%v\n", r.Header)
|
|
fmt.Printf("fpath is:%s,afbs64 is:%s\n", bfpath, util.Base64dec(bfpath))
|
|
|
|
fmt.Printf("Downloading [%s]...\n", filename)
|
|
// 拼装完整路径
|
|
nfname := filepath.Join(config.G.FilePath, util.Base64dec(bfpath))
|
|
dirPath := filepath.Dir(nfname)
|
|
//dirPath := filepath.Dir(filename)
|
|
err = os.MkdirAll(dirPath, os.ModePerm)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
// 检查文件是否存在
|
|
if util.IsFileExist(nfname) {
|
|
// 当前时间
|
|
curtime := time.Now().Format("2006/01/02")
|
|
// 创建备份文件夹
|
|
bkdir := filepath.Join(config.G.FilePath, "backup", curtime)
|
|
// 递归创建文件夹
|
|
serr := os.MkdirAll(bkdir, os.ModePerm)
|
|
// 创建错误 返回空
|
|
if serr != nil {
|
|
return
|
|
}
|
|
|
|
// 文件重命名
|
|
//ddname := filename + "_backup_" + time.Now().Format("20060102150405")
|
|
ddname := filename + "_backup_" + time.Now().Format("20060102150405")
|
|
// 文件移动到备份目录下,并做压缩包
|
|
bkzip := filepath.Join(bkdir, ddname)
|
|
zfarr := []string{nfname}
|
|
util.ZipFiles(bkzip+".zip", zfarr, bkdir)
|
|
//渠道
|
|
// 加上路径
|
|
//fnewname := filepath.Join(bkdir, ddname)
|
|
//os.Rename(nfname, fnewname)
|
|
}
|
|
|
|
out, err := os.Create(nfname)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, file)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
// 如果单文件,需要先备份
|
|
|
|
// 如果收到的是zip文件,自动给解压缩
|
|
suf := strings.Split(filename, ".")
|
|
if suf[1] == "zip" {
|
|
// 传入实际路径
|
|
go util.DecompressZip(nfname)
|
|
}
|
|
|
|
fmt.Printf("[√] Download [%s] Success.\n", filename)
|
|
//
|
|
default:
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
|
|
// 输出接收结果
|
|
// fmt.Fprintf(w, "接收成功,并已经完成解压缩")
|
|
}
|
|
|
|
// 文件服务
|
|
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)
|
|
}
|
|
}
|
|
|
|
// 发送拦截
|
|
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
|
|
IsDir bool
|
|
FileName string
|
|
DownloadPath string
|
|
UrlPath string
|
|
Files []os.DirEntry
|
|
}{
|
|
DeviceName: config.G.DeviceName,
|
|
DownloadPath: downloadPath,
|
|
UrlPath: strings.TrimSuffix(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)
|
|
}
|
|
|
|
// 文件列表模板
|
|
tmpl, err := template.New("download").Parse(web.DownloadPage)
|
|
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)
|
|
}
|
|
case http.MethodPost:
|
|
// return file or folder information in JSON format for convenient send to the recipient
|
|
currentPath := config.G.FilePath
|
|
fileInfo, err := os.Stat(currentPath)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
var pathInfo struct {
|
|
Type string `json:"type"`
|
|
Paths []string `json:"paths"`
|
|
}
|
|
|
|
if fileInfo.IsDir() {
|
|
files, err := util.GetDirFilePaths(currentPath, true)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
pathInfo.Paths = files
|
|
pathInfo.Type = "dir"
|
|
} else {
|
|
pathInfo.Paths = []string{filepath.Base(currentPath)}
|
|
pathInfo.Type = "file"
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(pathInfo)
|
|
default:
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
}
|
|
|