409 lines
11 KiB
Go
409 lines
11 KiB
Go
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)
|
||
}
|
||
|
||
// 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
|
||
}
|