package file // 移植自 remote-backend-server internal/handlers/file(去 DB 依赖)。 import ( "fmt" "github.com/gin-gonic/gin" "github.com/jaypipes/ghw" "github.com/shirou/gopsutil/v3/disk" "net/http" "os" "path/filepath" "git.zeroonesoft.cn/golib/remote-core/common" "strconv" ) // RegisterRoutersGatewayFile 注册路由 func RegisterRoutersGatewayFile(r *gin.RouterGroup) { r.GET("/file/list", getGatewayFileList()) r.POST("/file/list", postGatewayFileList()) r.DELETE("/file", deleteGatewayFile()) r.PUT("/file/name", putGatewayFileName()) r.GET("/file/download", getGatewayFileDownload()) r.HEAD("/file/download", headGatewayFileDownload()) r.POST("/file/upload", postGatewayFileUpload()) r.POST("/file/dir", postGatewayFileDir()) } type PathData struct { Path string `json:"path"` } // 传递文件路径不方便 比如 路径中包含 # func getGatewayFileList() gin.HandlerFunc { return func(c *gin.Context) { dir := c.Query("path") data, err := getFileList(dir) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "操作成功", "data": gin.H{ "list": data, "count": len(data), "path": dir, }, }) } } func deleteGatewayFile() gin.HandlerFunc { return func(c *gin.Context) { path := c.Query("path") ok, err := common.PathExists(path) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } if !ok { if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + "文件不存在", "data": "OK", }) return } } err = os.Remove(path) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "操作成功", "data": nil, }) } } func putGatewayFileName() gin.HandlerFunc { return func(c *gin.Context) { oldPath := c.Query("old") newFile := c.Query("new") fileInfo, err := os.Stat(oldPath) if err != nil { if os.IsNotExist(err) { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + "文件不存在", "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } dir := filepath.Dir(oldPath) newPath := filepath.Join(dir, newFile) fmt.Println(fileInfo) fmt.Println(oldPath, newPath) err = os.Rename(oldPath, newPath) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "操作成功", "data": nil, }) } } func postGatewayFileDir() gin.HandlerFunc { return func(c *gin.Context) { dir := c.Query("dir") ok, err := common.PathExists(dir) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } if ok { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + "文件不存在", "data": "OK", }) return } err = os.MkdirAll(dir, 0750) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "操作成功", "data": nil, }) } } func postGatewayFileList() gin.HandlerFunc { return func(c *gin.Context) { dir := PathData{} err := c.BindJSON(&dir) fmt.Println("dir", dir) data, err := getFileList(dir.Path) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "error:" + err.Error(), "data": "OK", }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "操作成功", "data": gin.H{ "list": data, "count": len(data), "path": dir.Path, }, }) } } type FileInfo struct { Name string `json:"name"` Path string `json:"path"` Size int64 `json:"size"` Mode string `json:"mode"` ModTime string `json:"modTime"` IsDir bool `json:"isDir"` IsDrive bool `json:"isDrive"` Used int64 `json:"used"` DriveType string `json:"driveType"` } func getFileList(dir string) ([]FileInfo, error) { list := make([]FileInfo, 0) /*filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { list = append(list, FileInfo{ Name: info.Name(), Size: info.Size(), Mode: info.Mode().String(), ModTime: time.Time{}, IsDir: info.IsDir(), }) fmt.Println(info.Mode().Type()) return nil })*/ if dir == "" { partitions, err := disk.Partitions(false) //fmt.Printf("disk partitions:%v\n\n", partitions) if err != nil { // return nil, err } block, err := ghw.Block() for i, partition := range partitions { usage, err := disk.Usage(partitions[i].Mountpoint) if err != nil { break } label, err := getVolumeName(partition.Device) name := label if label != partition.Device { name = name + " (" + partition.Device + ")" } driveType := "" for _, d := range block.Disks { // fmt.Printf(" %v\n", disk.StorageController) for _, part := range d.Partitions { if part.Name == partition.Device { driveType = d.DriveType.String() break } } } list = append(list, FileInfo{ Name: name, Path: partition.Mountpoint + "/", Size: int64(usage.Total), Used: int64(usage.Used), Mode: "", ModTime: "", IsDir: false, IsDrive: true, DriveType: driveType, }) } return list, nil } f, err := os.Open(dir) if err != nil { fmt.Println(err) } files, err := f.Readdir(-1) f.Close() if err != nil { fmt.Println(err) } for _, file := range files { list = append(list, FileInfo{ Name: file.Name(), Path: filepath.Join(dir, file.Name()), Size: file.Size(), Mode: file.Mode().String(), ModTime: file.ModTime().Format("2006-01-02 15:04:05"), IsDir: file.IsDir(), }) } return list, nil } func getGatewayFileDownload() gin.HandlerFunc { return func(c *gin.Context) { filePath := c.Query("filename") fileName := filepath.Base(filePath) c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename="+fileName) c.Header("Content-Transfer-Encoding", "binary") fi, err := os.Stat(filePath) if err == nil { c.Header("Content-Length", strconv.FormatInt(fi.Size(), 10)) } c.File(filePath) } } func headGatewayFileDownload() gin.HandlerFunc { return func(c *gin.Context) { filePath := c.Query("filename") fileName := filepath.Base(filePath) c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename="+fileName) c.Header("Content-Transfer-Encoding", "binary") fmt.Println(filePath) fi, err := os.Stat(filePath) if err == nil { fmt.Println("file size is ", fi.Size(), err) } c.Header("Content-Length", strconv.FormatInt(fi.Size(), 10)) } } type Win32_Volume struct { Name string Label string } type FileData struct { OriginalFileName string `json:"originalFileName"` FileName string `json:"fileName"` FilePath string `json:"filePath"` Size int64 `json:"size"` Md5 string `json:"md5"` } func postGatewayFileUpload() gin.HandlerFunc { return func(c *gin.Context) { dir := c.Query("dir") file, err := HttpUploadFile(c, dir) if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1, "msg": "上传失败:" + err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "success", "status": "done", "file": file, }) } } func HttpUploadFile(c *gin.Context, saveDir string) (*FileData, error) { file, err := c.FormFile("file") if err != nil { return nil, err } fileName := file.Filename // 保存路径 绝对路径 savePath := filepath.Join(saveDir, file.Filename) err = c.SaveUploadedFile(file, savePath) if err != nil { return nil, err } fileData := &FileData{ OriginalFileName: file.Filename, FileName: fileName, FilePath: savePath, Size: file.Size, } return fileData, nil }