User Tools

Site Tools


Simple filestore on Golang

Now is very ditry but work =)

filestore.go
/*
 * 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
}