wip
This commit is contained in:
parent
cbbb907d6a
commit
dd66f73157
4 changed files with 97 additions and 111 deletions
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* @Author: LinkLeong link@icewhale.com
|
||||
* @Date: 2021-10-08 10:29:08
|
||||
* @LastEditors: LinkLeong
|
||||
* @LastEditTime: 2022-07-22 11:06:07
|
||||
* @FilePath: /CasaOS/middleware/gin.go
|
||||
* @Description:
|
||||
* @Website: https://www.casaos.io
|
||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||
*/
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func Cors() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
method := c.Request.Method
|
||||
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
||||
// 允许跨域设置可以返回其他子段,可以自定义字段
|
||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With")
|
||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
||||
// c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
|
||||
// 设置缓存时间
|
||||
c.Header("Access-Control-Max-Age", "172800")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
c.Set("Content-Type", "application/json")
|
||||
//}
|
||||
|
||||
// 允许类型校验
|
||||
if method == "OPTIONS" {
|
||||
c.JSON(http.StatusOK, "ok!")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println(err)
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func WriteLog() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if !strings.Contains(c.Request.URL.String(), "password") {
|
||||
loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method))
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -362,21 +362,27 @@ func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
|
|||
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
||||
fullPath := path
|
||||
|
||||
IsNotExistCreateFile(fullPath)
|
||||
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, _ := os.OpenFile(fullPath,
|
||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||
0o666,
|
||||
)
|
||||
|
||||
defer file.Close()
|
||||
|
||||
bufferedWriter := bufio.NewWriter(file)
|
||||
|
||||
// todo: here should have a goroutine to remove each partial file after it is read, to save disk space
|
||||
|
||||
for i := 0; i < length+startPoint; i++ {
|
||||
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bufferedWriter.Write(data)
|
||||
if err != nil {
|
||||
if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package route
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS-Common/middleware"
|
||||
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
|
||||
"github.com/IceWhaleTech/CasaOS/middleware"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||
|
||||
|
@ -11,12 +13,22 @@ import (
|
|||
)
|
||||
|
||||
func InitRouter() *gin.Engine {
|
||||
r := gin.Default()
|
||||
ginMode := gin.ReleaseMode
|
||||
if config.ServerInfo.RunMode != "" {
|
||||
ginMode = config.ServerInfo.RunMode
|
||||
}
|
||||
if os.Getenv(gin.EnvGinMode) != "" {
|
||||
ginMode = os.Getenv(gin.EnvGinMode)
|
||||
}
|
||||
gin.SetMode(ginMode)
|
||||
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
r.Use(middleware.Cors())
|
||||
r.Use(middleware.WriteLog())
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
gin.SetMode(config.ServerInfo.RunMode)
|
||||
if ginMode != gin.ReleaseMode {
|
||||
r.Use(middleware.WriteLog())
|
||||
}
|
||||
|
||||
// r.StaticFS("/ui", http.FS(web.Static))
|
||||
// r.GET("/", WebUIHome)
|
||||
|
|
112
route/v1/file.go
112
route/v1/file.go
|
@ -18,9 +18,11 @@ import (
|
|||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// @Summary 读取文件
|
||||
|
@ -47,7 +49,7 @@ func GetFilerContent(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
}
|
||||
//文件读取任务是将文件内容读取到内存中。
|
||||
// 文件读取任务是将文件内容读取到内存中。
|
||||
info, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||
|
@ -83,7 +85,6 @@ func GetLocalFile(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
c.File(path)
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary download
|
||||
|
@ -96,7 +97,6 @@ func GetLocalFile(c *gin.Context) {
|
|||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/download [get]
|
||||
func GetDownloadFile(c *gin.Context) {
|
||||
|
||||
t := c.Query("format")
|
||||
|
||||
files := c.Query("files")
|
||||
|
@ -135,11 +135,11 @@ func GetDownloadFile(c *gin.Context) {
|
|||
}
|
||||
if !info.IsDir() {
|
||||
|
||||
//打开文件
|
||||
// 打开文件
|
||||
fileTmp, _ := os.Open(filePath)
|
||||
defer fileTmp.Close()
|
||||
|
||||
//获取文件的名称
|
||||
// 获取文件的名称
|
||||
fileName := path.Base(filePath)
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||
c.File(filePath)
|
||||
|
@ -179,7 +179,6 @@ func GetDownloadFile(c *gin.Context) {
|
|||
log.Printf("Failed to archive %s: %v", fname, err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetDownloadSingleFile(c *gin.Context) {
|
||||
|
@ -202,7 +201,7 @@ func GetDownloadSingleFile(c *gin.Context) {
|
|||
defer fileTmp.Close()
|
||||
|
||||
fileName := path.Base(filePath)
|
||||
//c.Header("Content-Disposition", "inline")
|
||||
// c.Header("Content-Disposition", "inline")
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||
c.File(filePath)
|
||||
}
|
||||
|
@ -248,7 +247,7 @@ func DirPath(c *gin.Context) {
|
|||
info[i].Extensions = ex
|
||||
}
|
||||
}
|
||||
//Hide the files or folders in operation
|
||||
// Hide the files or folders in operation
|
||||
fileQueue := make(map[string]string)
|
||||
if len(service.OpStrArr) > 0 {
|
||||
for _, v := range service.OpStrArr {
|
||||
|
@ -361,7 +360,6 @@ func PostCreateFile(c *gin.Context) {
|
|||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/upload [get]
|
||||
func GetFileUpload(c *gin.Context) {
|
||||
|
||||
relative := c.Query("relativePath")
|
||||
fileName := c.Query("filename")
|
||||
chunkNumber := c.Query("chunkNumber")
|
||||
|
@ -405,55 +403,92 @@ func PostFileUpload(c *gin.Context) {
|
|||
hash := file.GetHashByContent([]byte(fileName))
|
||||
|
||||
if len(path) == 0 {
|
||||
c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||
loger.Error("path should not be empty")
|
||||
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
|
||||
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||
|
||||
if fileName != relative {
|
||||
dirPath = strings.TrimSuffix(relative, fileName)
|
||||
tempDir += dirPath
|
||||
file.MkDir(path + "/" + dirPath)
|
||||
if err := file.MkDir(path + "/" + dirPath); err != nil {
|
||||
loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
path += "/" + relative
|
||||
|
||||
if !file.CheckNotExist(tempDir + chunkNumber) {
|
||||
file.RMDir(tempDir + chunkNumber)
|
||||
if err := file.RMDir(tempDir + chunkNumber); err != nil {
|
||||
loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if totalChunks > 1 {
|
||||
file.IsNotExistMkDir(tempDir)
|
||||
|
||||
out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
defer out.Close()
|
||||
_, err := io.Copy(out, f)
|
||||
if err != nil {
|
||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||
if err := file.IsNotExistMkDir(tempDir); err != nil {
|
||||
loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||
if err != nil {
|
||||
loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
|
||||
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||
loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
fileNum, err := ioutil.ReadDir(tempDir)
|
||||
if err != nil {
|
||||
loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if totalChunks == len(fileNum) {
|
||||
if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
|
||||
loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := file.RMDir(tempDir); err != nil {
|
||||
loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
defer out.Close()
|
||||
_, err := io.Copy(out, f)
|
||||
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||
if err != nil {
|
||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||
loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||
return
|
||||
}
|
||||
fileNum, err := ioutil.ReadDir(tempDir)
|
||||
if err != nil {
|
||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
if totalChunks == len(fileNum) {
|
||||
file.SpliceFiles(tempDir, path, totalChunks, 1)
|
||||
file.RMDir(tempDir)
|
||||
}
|
||||
|
||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||
defer out.Close()
|
||||
|
||||
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||
loger.Error("error when trying to write to `"+path+"`", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary copy or move file
|
||||
|
@ -465,7 +500,6 @@ func PostFileUpload(c *gin.Context) {
|
|||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/operate [post]
|
||||
func PostOperateFileOrDir(c *gin.Context) {
|
||||
|
||||
list := model.FileOperate{}
|
||||
c.ShouldBind(&list)
|
||||
|
||||
|
@ -515,7 +549,6 @@ func PostOperateFileOrDir(c *gin.Context) {
|
|||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/delete [delete]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
|
||||
paths := []string{}
|
||||
c.ShouldBind(&paths)
|
||||
if len(paths) == 0 {
|
||||
|
@ -547,7 +580,6 @@ func DeleteFile(c *gin.Context) {
|
|||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/update [put]
|
||||
func PutFileContent(c *gin.Context) {
|
||||
|
||||
fi := model.FileUpdate{}
|
||||
c.ShouldBind(&fi)
|
||||
|
||||
|
@ -557,7 +589,7 @@ func PutFileContent(c *gin.Context) {
|
|||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
||||
return
|
||||
}
|
||||
//err := os.Remove(path)
|
||||
// err := os.Remove(path)
|
||||
err := os.RemoveAll(fi.FilePath)
|
||||
if err != nil {
|
||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
||||
|
|
Loading…
Add table
Reference in a new issue