mirror of https://gitee.com/godoos/godoos.git
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.
461 lines
12 KiB
461 lines
12 KiB
package files
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"godo/libs"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func HandleSystemInfo(w http.ResponseWriter, r *http.Request) {
|
|
info := libs.GetSystemInfo()
|
|
|
|
// res := libs.APIResponse{
|
|
// Message: "File information retrieved successfully.",
|
|
// Data: info,
|
|
// }
|
|
//json.NewEncoder(w).Encode(res)
|
|
libs.SuccessMsg(w, info, "File information retrieved successfully.")
|
|
}
|
|
|
|
// HandleReadDir handles reading a directory
|
|
func HandleReadDir(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
files, err := ReadDir(basePath, path)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
var osFileInfos []OsFileInfo
|
|
for _, entry := range files {
|
|
// 过滤掉以.开头的文件(隐藏文件)
|
|
if strings.HasPrefix(entry.Name(), ".") {
|
|
continue
|
|
}
|
|
osFileInfo, err := GetFileInfo(entry, basePath, path)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
// 如果是文件,读取内容
|
|
if osFileInfo.IsFile {
|
|
file, err := os.Open(filepath.Join(basePath, osFileInfo.Path))
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to open file: %v", err))
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
content, err := io.ReadAll(file)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to read file content: %v", err))
|
|
return
|
|
}
|
|
osFileInfo.Content = string(content)
|
|
|
|
// 检查文件内容是否以"link::"开头
|
|
if strings.HasPrefix(osFileInfo.Content, "link::") {
|
|
osFileInfo.IsSymlink = true
|
|
} else {
|
|
osFileInfo.Content = ""
|
|
}
|
|
}
|
|
|
|
osFileInfos = append(osFileInfos, *osFileInfo)
|
|
}
|
|
// 按照 ModTime 进行降序排序
|
|
sort.Slice(osFileInfos, func(i, j int) bool {
|
|
return osFileInfos[i].ModTime.Before(osFileInfos[j].ModTime)
|
|
})
|
|
res := libs.APIResponse{
|
|
Message: "Directory read successfully.",
|
|
Data: osFileInfos,
|
|
}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleStat retrieves file information
|
|
func HandleStat(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
// 调用GetFileInfo,传入路径而不是fs.DirEntry
|
|
osFileInfo, err := GetFileInfo(path, basePath, "")
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusNotFound, err.Error())
|
|
return
|
|
}
|
|
|
|
res := libs.APIResponse{
|
|
Message: "File information retrieved successfully.",
|
|
Data: osFileInfo,
|
|
}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleExists checks if a file or directory exists
|
|
func HandleExists(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
exists := Exists(basePath, path)
|
|
message := "File does not exist."
|
|
if exists {
|
|
message = "File exists."
|
|
}
|
|
res := libs.APIResponse{
|
|
Message: message,
|
|
Data: exists,
|
|
}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleReadFile reads a file's content
|
|
func HandleReadFile(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
fileContent, err := ReadFile(basePath, path)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusNotFound, err.Error())
|
|
return
|
|
}
|
|
content := string(fileContent)
|
|
// 检查文件内容是否以"link::"开头
|
|
if !strings.HasPrefix(content, "link::") {
|
|
content = base64.StdEncoding.EncodeToString(fileContent)
|
|
}
|
|
res := libs.APIResponse{
|
|
Message: fmt.Sprintf("File '%s' read successfully.", path),
|
|
Data: content, // Optionally, encode content as base64 for transmission
|
|
//Data: string(fileContent),
|
|
}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleUnlink removes a file
|
|
func HandleUnlink(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = Unlink(basePath, path)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("File '%s' successfully removed.", path)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleClear removes the entire filesystem (Caution: Use with care!)
|
|
func HandleClear(w http.ResponseWriter, r *http.Request) {
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = Clear(basePath)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: "FileSystem successfully cleared."}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleRename renames a file
|
|
func HandleRename(w http.ResponseWriter, r *http.Request) {
|
|
oldPath := r.URL.Query().Get("oldPath")
|
|
newPath := r.URL.Query().Get("newPath")
|
|
if err := validateFilePathPair(oldPath, newPath); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = Rename(basePath, oldPath, newPath)
|
|
if err != nil {
|
|
log.Printf("Error renaming file: %s", err.Error())
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("File '%s' successfully renamed to '%s'.", oldPath, newPath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleMkdir creates a directory
|
|
func HandleMkdir(w http.ResponseWriter, r *http.Request) {
|
|
dirPath := r.URL.Query().Get("dirPath")
|
|
if err := validateFilePath(dirPath); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = Mkdir(basePath, dirPath)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("Directory '%s' created successfully.", dirPath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleRmdir removes a directory
|
|
func HandleRmdir(w http.ResponseWriter, r *http.Request) {
|
|
dirPath := r.URL.Query().Get("dirPath")
|
|
if err := validateFilePath(dirPath); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = Rmdir(basePath, dirPath)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("Directory '%s' successfully removed.", dirPath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleCopyFile copies a file
|
|
func HandleCopyFile(w http.ResponseWriter, r *http.Request) {
|
|
srcPath := r.URL.Query().Get("srcPath")
|
|
dstPath := r.URL.Query().Get("dstPath")
|
|
if err := validateFilePathPair(srcPath, dstPath); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = CopyFile(filepath.Join(basePath, srcPath), filepath.Join(basePath, dstPath))
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("File '%s' successfully copied to '%s'.", srcPath, dstPath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleWriteFile writes content to a file
|
|
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {
|
|
filePath := r.URL.Query().Get("filePath")
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
// 获取文件内容
|
|
fileContent, _, err := r.FormFile("content")
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
defer fileContent.Close()
|
|
// 输出到控制台进行调试
|
|
fmt.Printf("Body content: %v\n", fileContent)
|
|
file, err := os.Create(filepath.Join(basePath, filePath))
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
_, err = io.Copy(file, fileContent)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusConflict)
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("File '%s' successfully written.", filePath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleAppendFile appends content to a file
|
|
func HandleAppendFile(w http.ResponseWriter, r *http.Request) {
|
|
filePath := r.URL.Query().Get("filePath")
|
|
if err := validateFilePath(filePath); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
content, _, err := r.FormFile("content")
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
err = AppendToFile(filepath.Join(basePath, filePath), content)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("Content appended to file '%s'.", filePath)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// HandleChmod changes the permissions of a file
|
|
func HandleChmod(w http.ResponseWriter, r *http.Request) {
|
|
var reqData struct {
|
|
Path string `json:"path"`
|
|
Mode string `json:"mode"`
|
|
}
|
|
|
|
// 解析请求体
|
|
err := json.NewDecoder(r.Body).Decode(&reqData)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, "Failed to parse request body")
|
|
return
|
|
}
|
|
|
|
// 使用解码后的数据
|
|
path := reqData.Path
|
|
modeStr := reqData.Mode
|
|
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
mode, err := parseMode(modeStr)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, fmt.Sprintf("Invalid mode: %s", err.Error()))
|
|
return
|
|
}
|
|
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
err = Chmod(basePath, path, mode)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
|
|
res := libs.APIResponse{Message: fmt.Sprintf("Permissions of file '%s' successfully changed to %o.", path, mode)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
func HandleZip(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
ext := r.URL.Query().Get("ext")
|
|
if ext == "" {
|
|
ext = "zip"
|
|
}
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.HTTPError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
sourcePath := filepath.Join(basePath, path)
|
|
compressedFilePath := filepath.Join(basePath, path+"."+ext)
|
|
err = CompressFileOrFolder(sourcePath, compressedFilePath)
|
|
if err != nil {
|
|
libs.HTTPError(w, http.StatusConflict, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("success zip %s.%s.", path, ext)}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
func HandleUnZip(w http.ResponseWriter, r *http.Request) {
|
|
path := r.URL.Query().Get("path")
|
|
|
|
if err := validateFilePath(path); err != nil {
|
|
libs.ErrorMsg(w, err.Error())
|
|
return
|
|
}
|
|
|
|
basePath, err := libs.GetOsDir()
|
|
if err != nil {
|
|
libs.ErrorMsg(w, err.Error())
|
|
return
|
|
}
|
|
|
|
zipFilePath := filepath.Join(basePath, path)
|
|
destPath := filepath.Dir(zipFilePath)
|
|
zipPath, err := Decompress(zipFilePath, destPath)
|
|
if err != nil {
|
|
libs.ErrorMsg(w, err.Error())
|
|
return
|
|
}
|
|
res := libs.APIResponse{Message: fmt.Sprintf("success unzip %s.", path), Data: zipPath}
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
// parseMode converts a string representation of a mode to an os.FileMode
|
|
func parseMode(modeStr string) (os.FileMode, error) {
|
|
mode, err := strconv.ParseUint(modeStr, 8, 32)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return os.FileMode(mode), nil
|
|
}
|
|
|