跳转至

其他

拦截器

  • 在代码生成的例子中,我们添加了一个基础类型BaseLoginedService:
    package service
    
    import (
        "github.com/ie310mu/ie310go/route"
    )
    
    //BaseLoginedService ..
    type BaseLoginedService struct {
        route.BaseService
    }
    
    //BeforeExcute ..
    func (s BaseLoginedService) BeforeExcute(args *route.ServiceArgs) {
    }
    
    //AfterExcute ..
    func (s BaseLoginedService) AfterExcute(args *route.ServiceArgs) {
    }
    
  • 在此类型中,可以通过对BeforeExcute、AfterExcute的扩展,做一些拦截的操作(比如BeforeExcute中检查是否有登录信息,没有时直接panic即可)、调用后处理。
  • 也可以通过定义BaseLoginedService的基础类型,实现更多的拦截器操作
  • 注意,这里的“拦截器”是通过类的继承来实现的,和真正的“拦截器”有一定差别

session

  • httpServer中提供对session的支持(但不推荐使用,ie310go推荐的方式是自定义token的方式)
  • 要启用session,使用如下代码:
    ie310go.AppSessionInitFunc = session.Init
    //.....other code
    ie310go.Run(nil)
    
    //Init ..
    func Init() {
        sessionConfig := &session.ManagerConfig{
            Gclifetime:      3600,
            Maxlifetime:     3600,
            Secure:          false,
            CookieLifeTime:  3600,
            ProviderConfig:  "./tmp",
        }
    
        //config.Config.RedisURL指示是否使用redis保存session,示例值  127.0.0.1:6379
        if config.Config.RedisURL != "" {
            logsagent.Info("session where init as redis : " + config.Config.RedisURL)
            sessionConfig.ProviderConfig = config.Config.RedisURL
            gs, err := session.NewManager("redis", sessionConfig)
            throw.CheckErr(err)
            session.GlobalSessions = gs
            logsagent.Info("session init as redis : " + config.Config.RedisURL)
        } else {
            logsagent.Info("session where init as memory ")
            gs, err := session.NewManager("memory", sessionConfig)
            throw.CheckErr(err)
            session.GlobalSessions = gs
            logsagent.Info("session init as memory ")
        }
    
        go session.GlobalSessions.GC()
    }
    

上传文件

  • 示例代码(摘取自 i3work):
    //UploadFile 只能用于http协议,需要附加参数&packageResult=false&convertResult=false
    func (s TaskRecordService) UploadFile(args *route.ServiceArgs) (result string) {
        defer func() {
            if err := recover(); err != nil {
                result = fmt.Sprintf("%v", err)
            }
        }()
    
        rs := args.GetRs().(*route.RequestResponseHTTP)
        r := rs.GetR()
        err := r.ParseMultipartForm(18 * 1024) 
        throw.CheckErr(err)
        taskID := args.GetStringParamWithCheck("taskId", false)
        actionID := args.GetStringParamWithCheck("actionId", true)
        fileSize := args.GetIntParam("fileSize")
        upFileName := args.GetStringParamWithCheck("fileName", false)
    
        userutil.CheckRole(args, userutil.DefaultError, "file")
        task := mapper.GetTaskRecordMapper("ro").Get(nil, taskID)
        userutil.CheckProjectPower(args, userutil.DefaultError, task.ProjectCode)
    
        //获取handler
        file, handler, err := r.FormFile("file")
        throw.CheckErr(err)
        defer file.Close()
    
        //fileSize
        if fileSize > 100*1024*1024 {
            panic("文件不能超过100M")
        }
        fileSizeKB := float64(fileSize) / float64(1024)
        fileSizeKB = math.RoundToEven(fileSizeKB)
        fmt.Println(fileSizeKB)
    
        defer func() {
            if err := recover(); err != nil {
                result = obj.InterfaceToStr(err)
            }
        }()
    
        //md5
        body, err := ioutil.ReadAll(file)
        if err != nil {
            fmt.Println("ReadAll", err)
            return
        }
        //md5.Sum(body)
        md5Value := fmt.Sprintf("%x", md5.Sum(body))
        fmt.Println(md5Value)
    
        //文件类型
        ext := path.Ext(handler.Filename)
        if ext == "" {
            panic("文件没有后缀名")
        }
        ext = strings.ToLower(ext)
        if ext != ".xls" && ext != ".xlsx" && ext != ".doc" && ext != ".docx" && ext != ".pdf" && ext != ".rar" && ext != ".zip" && ext != ".jpeg" && ext != ".jpg" && ext != ".png" && ext != ".txt" && ext != ".sql" {
            panic("仅支持文件后缀名为xls、xlsx、doc、docx、pdf、rar、zip、jpeg、jpg、png、txt、sql")
        }
        fmt.Println(ext)
    
        //创建数据记录
        mp := mapper.GetTaskActionMapper("")
        des := upFileName
        action := taskutil.CreateAction(args, taskID, "上传附件", des, false)
        if actionID != "" {
            action = mp.Get(nil, actionID)
            action.Des = des
        }
        action.Md5 = md5Value
        action.Ext = ext
        action.ExtSize = float32(fileSize)
        action.ExtSize = action.ExtSize / float32(1024)
    
        //保存文件
        fileName := s.getUploadFileName(md5Value, ext)
        if !dir.PathExists(fileName) {
            f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0666)
            throw.CheckErr(err)
            defer f.Close()
            file.Seek(0, 0)
            io.Copy(f, file)
        }
    
        if actionID == "" {
            mp.Insert(nil, action)
            userutil.SaveAction(nil, args, "上传附件:"+upFileName, task)
        } else {
            mp.Update(nil, action)
            userutil.SaveAction(nil, args, "替换附件:"+upFileName, task)
        }
    
        rs.CustomContentType = "text/html;charset=utf-8"
        return `<!DOCTYPE html>
        <html>
    
        <body class="layui-layout-body">
            上传成功
            <script src="/packages/layui/layui.all.js"></script>
            <script src="/js/base.js"></script>
            <script>
                $(function () {
                    setTimeout(() => {
                        window.top.closeFrm(true, "addFile");
                    }, 500);
                })
            </script>
        </body>
    
        </html>`
    }
    
    <form action="/taskRecordService.goss?m=uploadFile&packageResult=false&convertResult=false&cu=false"  method="post" enctype="multipart/form-data" id="form">
                    <div class="layui-layout layui-layout-admin">
                        <div class="layui-body" style="top: 0px;left:0px;padding: 30px;">
                                <input type="hidden" id="taskId" name="taskId" />
                                <input type="hidden" id="actionId" name="actionId" />
                                <input type="hidden" id="fileSize" name="fileSize" />
                                <input type="hidden" id="fileName" name="fileName" />
                                <input type="hidden" id="token" name="token" />
                                <span id="fileNameSpan"></span>
                                <br />
                                <br />
                                <input class="dn" type="file" id="file" name="file" onchange="fileChanged(this.files);" />
                        </div>
    
                        <div class="layui-footer" style="left: 0px;height: 60px;z-index: 999;">
                            <div class="layui-btn-container" style="width: 100%;padding-top: 10px;">
                                <button type="button" class="layui-btn " style="float: left;"
                                    onclick="selectFile();">选择文件</button>
                                <button type="button" class="layui-btn layui-btn-danger " style="float: right;" onclick="uploadFile();">上传</button>
                            </div>
                        </div>
                    </div>
    </form>
    

下载文件

  • 示例代码(摘取自 i3work):
    //DownloadFile ..
    func (s TaskRecordService) DownloadFile(args *route.ServiceArgs) {
        id := args.GetStringParamWithCheck("id", true)
        mp := mapper.GetTaskActionMapper("ro")
        action := mp.Get(nil, id)
        if action == nil {
            panic("附件不存在")
        }
        task := mapper.GetTaskRecordMapper("ro").Get(nil, action.TaskID)
        userutil.CheckProjectPower(args, userutil.DefaultError, task.ProjectCode)
    
        fileName := s.getUploadFileName(action.Md5, action.Ext)
        if !dir.PathExists(fileName) {
            panic("文件不存在")
        }
    
        file, err := os.Open(fileName)
        throw.CheckErr(err)
        defer file.Close()
    
        rs := args.GetRs().(*route.RequestResponseHTTP)
        rs.GetW().Header().Add("Content-Type", "application/octet-stream")
        rs.GetW().Header().Add("content-disposition", "attachment; filename=\""+action.Des+"\"")
        _, err = io.Copy(rs.GetW(), file)
        throw.CheckErr(err)
    }
    

httpServer的Content-Type默认值为application/json;charset=utf-8,可通过如下代码自定义:

rs.CustomContentType = "text/html;charset=utf-8"
上述代码适用于普通方法(返回值由ie310go封装成JSONServiceResult后转换为json字符串再输出),如果类似于上文中下载文件的输出方式(io.Copy(rs.GetW(), file)),则需要在Hearder中定义:
rs := args.GetRs().(*route.RequestResponseHTTP)
rs.GetW().Header().Add("Content-Type", "application/octet-stream")
rs.GetW().Header().Add("content-disposition", "attachment; filename=\""+action.Des+"\"")
_, err = io.Copy(rs.GetW(), file)
throw.CheckErr(err)

其他

  • redirect(暂未实现)