go session.Save gorm事务 打印sql文 axios上传多个文件 gin的binding数据检验

项目介绍:
    代码地址:https://github.com/hitgub123/golang/tree/master/gingorm
    使用技术:
        go(gin gorm),postgresql
        vue(无脚手架),axios
        gin-contrib/sessions
        gin-contrib/sessions/cookie
    大部分功能前后端分离,mvc架构,实现了增删改查,数据校验,多文件上传

使用"github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie",
Set,Delete等方法修改session后必须session.Save()才生效

结构体字段是int时,前端ajax post请求传参也要是int,传string会无法接收

gorm的事务处理:
    func TestTX() {
        tx := GetDB().Begin()
        defer func() {
            if err := recover(); err != nil {
                tx.Rollback()
            } else {
                tx.Commit()
            }
        }()
        tx.Create(&obj.User{Name: "Giraffe"})
        zero := 0
        log.Println("InsertUser>>", 1/zero)
        tx.Create(&obj.User{Name: "Lion"})

    }

gorm打印sql文
	db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
		Logger:logger.Default.LogMode(logger.Info),	
	})
    

axios(多个或者单个)上传文件,代码见static\html\user.html
    html部分
        文件1<input type='file' name='file11' ref='file1'/><br />
        文件2<input type='file' name='file22' ref='file2'/><br />
    js部分,这里用vue的refs取的文件,也可以用其他方法
          let params = new FormData();
          //append到同一个key,会自动创建数组。这里设置什么key,后台接收的map就用什么key
          params.append('file666', this.$refs.file1.files[0])        
          params.append('file666', this.$refs.file1.files[0])
          const config = {
            headers: { "Content-Type": "multipart/form-data" }
          }
          axios.post("/u/insert", params,config)
    后台部分,使用go
        f, err = c.MultipartForm()
        if err != nil {
            goto End
        } else {         
            files:= f.File
            //files:map[file666:[0xc00007e230 0xc00007e050]],可以直接遍历files['file666']来取得单个文件
            //这里key是html文件里file的name属性(即file666),files_[]*FileHeader(FileHeader切片)
            for key, files_ := range files {
                for index,f :=range(files_){
                    // f := files_[0]       //单文件上传时取第一个文件即可
                    //path.Ext获取文件后缀名,好像前方自带小数点
                    dest := fmt.Sprintf("static/upload/%d-%s%s", time.Now().Nanosecond(), key, path.Ext(f.Filename))
                    if err = c.SaveUploadedFile(f, dest); err != nil {
                        goto End
                    }
                }
            }
        }

vue拼接字符串和变量:<img style='height:100px' :src='"/"+value.pic' />

为了方便学习比对,user的insert方法提交了文件,update方法没提交文件。
代码见 static\html\user.html的js部分 和 controller\userController.go的update和insert方法

文件上传的multipart/form-data表单,shouldbind似乎无法绑定参数,可以用PostForm绑定

同一个包下可以直接调用其他go文件的public方法

在结构体中对field添加binding属性,
    结构体可以写在dao层等其他地方,
    使用Query或者PostForm不会进行校验,
    如果提交的表单是MultipartForm,不会进行校验,
    使用ShouldBind/Bind进行检验。如果产生error,必须手动处理。否则会继续无视校验规则绑定成功,代码如下:
	if err:= c.ShouldBind(&o); err != nil {
		log.Println("err",err)
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	} 
    可以把参数放请求头里,用ShouldBindHeader获取,
        比如headers: { "Content-Type": "multipart/form-data","name":this.user.name }
	放汉字报错String contains non ISO-8859-1 code point,需要转码

重定向遇到的method的bug:
    访问项目时,使用中间件查看session里有没有user字段,
    如果没有就重定向到login,login的get/post和logout没有使用中间件。
    代码是c.Redirect(http.StatusPermanentRedirect , "/login")。
    发现get方法访问就get到此页面(正常),post访问就post到此页面(异常),
    因为post用来提交登录信息。需要全都设置为get方法。
    一开始修改c.Request.Method="GET",发现method是改了,依旧是POST请求。
    解决方法:
        重定向代码改成c.Redirect(http.StatusMovedPermanently , "/login")
        参考https://gin-gonic.com/zh-cn/docs/examples/redirects/
        和http://psychedelicnekopunch.com/archives/1848
    推荐使用301(StatusMovedPermanently)302(StatusFound)

    

    

你可能感兴趣的:(gin,golang,golang,gin)