Now is very ditry but work
/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ package main import ( "github.com/gin-gonic/gin" //"github.com/sevlyar/go-daemon" "net/http" "fmt" "log" "path/filepath" "os" "path" "time" "io" "mime/multipart" ) func main() { context := &daemon.Context{ PidFileName: "gin.pid", PidFilePerm: 0644, LogFileName: "gin.log", LogFilePerm: 0640, WorkDir: "./", Umask: 027, Args: []string{""}, } child, err := context.Reborn() if err != nil { log.Fatal("unable to run: ", err) } if child != nil { return } defer context.Release() log.Println("daemon started") ginStart() } func logFormatter() func(param gin.LogFormatterParams) string { return func(param gin.LogFormatterParams) string { return fmt.Sprintf("%s - [%s] %s %s %s %d %s \"%s\" \"%s\"\n", param.ClientIP, param.TimeStamp.Format(time.RFC3339), param.Method, param.Path, param.Request.Proto, param.StatusCode, param.Latency, param.Request.UserAgent(), param.ErrorMessage, ) } } func ginStart() { //gin.SetMode(gin.DebugMode) gin.SetMode(gin.ReleaseMode) gin.DisableConsoleColor() logFile, err := os.Create("access.log") if err != nil { panic(err) } gin.DefaultWriter = io.MultiWriter(logFile, os.Stdout) //log.SetOutput(gin.DefaultWriter) router := gin.New() router.Use(gin.LoggerWithFormatter(logFormatter())) router.MaxMultipartMemory = 8 << 20 // 8 MiB accounts := gin.Accounts{ "foo": "bar", } authorized := router.Group("/api", gin.BasicAuth(accounts)) authorized.GET("/hello", func(context *gin.Context) { user := context.MustGet(gin.AuthUserKey).(string) context.JSON(http.StatusOK, gin.H{ "message": "hello " + user, }) }) authorized.GET("/index", func(context *gin.Context) { context.JSON(http.StatusOK, gin.H{ "result" : listDir("/data/music", "*"), }) }) authorized.GET("/get", func(context *gin.Context) { type Req struct { Name string `form:"name" json:"name"` } var req Req if context.ShouldBind(&req) == nil { context.JSON(http.StatusOK, gin.H{ "result" : req, }) } }) authorized.POST("/upload", func(context *gin.Context) { type BindFile struct { Name string `form:"name" binding:"required"` File *multipart.FileHeader `form:"file" binding:"required"` } var bindFile BindFile if err := context.ShouldBind(&bindFile); err != nil { context.String(http.StatusBadRequest, fmt.Sprintf("err: %s", err.Error())) return } file := bindFile.File dest := "upl_" + filepath.Base(file.Filename) if err := context.SaveUploadedFile(file, dest); err != nil { context.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error())) return } type Result struct { Name string `json:"name"` } res := Result{ Name: file.Filename, } context.JSON(http.StatusOK, gin.H{ "result": res, }) }) authorized.GET("/download", func(context *gin.Context) { type Req struct { Name string `form:"name" json:"name"` } var req Req err := context.ShouldBind(&req); if err == nil && FileExists(req.Name) { context.FileAttachment(req.Name, "down_" + req.Name) return } else { context.Status(http.StatusNotFound) } }) router.Run(":8089") } func FileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { return false } } return true } type File struct { Name string `json:"name"` Size int64 `json:"size"` } func listDir (dir string, glob string) []File { files, err := filepath.Glob(path.Join(dir, glob)) if err != nil { log.Fatal(err) } list := []File{} for i := 0; i < len(files); i++ { name := files[i] fi, err := os.Stat(name); if err != nil { log.Fatal(err) continue } if fi.IsDir() { continue } item := File{ Name: fi.Name(), Size: fi.Size(), } list = append(list, item) } return list }