英文:
Multipart File Upload Validation in gin-gonic
问题
我正在尝试为基于GIN框架的Go Web应用程序添加验证。在网页上,我选择一个文件并提交,然后服务器对其进行处理。
在服务器端,我试图添加验证以检查是否提供了文件。如果没有提供,则重定向回原始页面。
func panic(err error) {
	if err != nil {
		log.Println(err)
	}
}
func displayTable(c *gin.Context) {
	file, _, err := c.Request.FormFile("file")
	panic(err)
	if file == nil {
		log.Println("File is nil.")
		log.Println(err)
		log.Println("*****")
		c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
			"title": "Select the input file", "error": "Please select the input file.",
		})
	} else {
		defer file.Close()
	}
	filename := strconv.FormatInt(time.Now().Unix(), 10)
	out, err := os.Create("./tmp/" + filename + ".xml")
	panic(err)
	defer out.Close()
	_, err = io.Copy(out, file)
	panic(err)
	xmlFile, err := os.Open("./tmp/" + filename + ".xml")
	panic(err)
	defer xmlFile.Close()
	// 其他实现细节
}
即使提供了处理程序,我仍然在Go代码中遇到了panic。请告诉我我在实现中漏掉了什么。
谢谢。
http: 没有该文件
File is nil.
http: 没有该文件
*****
2015/08/04 13:19:10 Panic recovery -> runtime error: invalid memory address or nil pointer dereference
c:/go/src/runtime/panic.go:387 (0x414d36)
c:/go/src/runtime/panic.go:42 (0x4142a5)
c:/go/src/runtime/os_windows.go:42 (0x414066)
c:/go/src/io/io.go:362 (0x45268f)
D:/code/src/exmp/serverexmaple.go:45 (0x40168f)
		displayTable: _, err = io.Copy(out, file)
D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
		(*Context).Next: c.handlers[c.index](c)
D:/code/src/github.com/gin-gonic/gin/logger.go:56 (0x4ac490)
		func.007: c.Next()
D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
		(*Context).Next: c.handlers[c.index](c)
D:/code/src/github.com/gin-gonic/gin/recovery.go:43 (0x4acc80)
		func.009: c.Next()
D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
		(*Context).Next: c.handlers[c.index](c)
D:/code/src/github.com/gin-gonic/gin/gin.go:292 (0x4a46d5)
		(*Engine).handleHTTPRequest: context.Next()
D:/code/src/github.com/gin-gonic/gin/gin.go:273 (0x4a4459)
		(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
c:/go/src/net/http/server.go:1703 (0x468415)
c:/go/src/net/http/server.go:1204 (0x466408)
c:/go/src/runtime/asm_386.s:2287 (0x438ea1)
英文:
I am trying to add validation for the go based web application based on  GIN framework. On the web page I am selecting a file and submitting and the server is processing it.
On the server side I am try to add validation to check if the file has been given or not. If not then redirect back to original page.
	func panic(err error)  {
		if err != nil {
			log.Println(err)
		}
	}
    func displayTable (c *gin.Context) {    
	file, _ , err := c.Request.FormFile("file")
	panic(err)
	if file == nil {
		log.Println("File is nil.")
		log.Println(err)
		log.Println("*****")
		c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
			"title": "Select the input file","error" : "Please select the input file.",
		})		
	} else {
		defer file.Close()
	}
	filename := strconv.FormatInt(time.Now().Unix(),10)	
	out, err := os.Create("./tmp/"+filename+".xml")
	panic(err)
	defer out.Close()
	_, err = io.Copy(out, file)
	panic(err)
	xmlFile, err := os.Open("./tmp/"+filename+".xml")
	panic(err)
	defer xmlFile.Close()
	
	// Other Implementation Details 
}
Even after providing the handling I am getting a panic in the go code. Please let me know what in the implementation am I missing.
Thanks.
	http: no such file
	File is nil.
	http: no such file
	*****
	2015/08/04 13:19:10 Panic recovery -> runtime error: invalid memory address or nil pointer dereference
	c:/go/src/runtime/panic.go:387 (0x414d36)
	c:/go/src/runtime/panic.go:42 (0x4142a5)
	c:/go/src/runtime/os_windows.go:42 (0x414066)
	c:/go/src/io/io.go:362 (0x45268f)
	D:/code/src/exmp/serverexmaple.go:45 (0x40168f)
			displayTable: _, err = io.Copy(out, file)
	D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
			(*Context).Next: c.handlers[c.index](c)
	D:/code/src/github.com/gin-gonic/gin/logger.go:56 (0x4ac490)
			func.007: c.Next()
	D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
			(*Context).Next: c.handlers[c.index](c)
	D:/code/src/github.com/gin-gonic/gin/recovery.go:43 (0x4acc80)
			func.009: c.Next()
	D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
			(*Context).Next: c.handlers[c.index](c)
	D:/code/src/github.com/gin-gonic/gin/gin.go:292 (0x4a46d5)
			(*Engine).handleHTTPRequest: context.Next()
	D:/code/src/github.com/gin-gonic/gin/gin.go:273 (0x4a4459)
			(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
	c:/go/src/net/http/server.go:1703 (0x468415)
	c:/go/src/net/http/server.go:1204 (0x466408)
	c:/go/src/runtime/asm_386.s:2287 (0x438ea1)
答案1
得分: 4
- 请不要重新定义
panic。这会让所有了解panic工作原理的人感到困惑。 - 在Go语言中,与
nil进行比较有点棘手。它可能不会按照你的预期工作:https://stackoverflow.com/questions/13476349/check-for-nil-and-nil-interface-in-go。FormFile返回一个接口,所以如果你想要用nil进行检查,你必须将其转换为底层结构,或者使用第二个参数,其类型是可用的。 - 这不仅适用于GIN,它是Go语言的HTTP实现的一部分:http://golang.org/pkg/net/http/#Request.FormFile
 
英文:
- Please do not redefine 
panic. It will confuse everyone who knows howpanicworks. - Comparison with nil is a bit tricky in Go. It may work not as you expect: https://stackoverflow.com/questions/13476349/check-for-nil-and-nil-interface-in-go. 
FormFilereturns interface so you have to cast it to underlying structure if you want to check it with nil OR use the second parameter, type of which is available. - This is not specific to GIN, it is part of the Go's HTTP implementation: http://golang.org/pkg/net/http/#Request.FormFile
 
答案2
得分: 0
我明白我在panic处理方面犯了错误。如果我在c.HTML之后添加返回语句,验证将会起作用。这将阻止函数执行其余的代码。感谢@AlexAtNet的建议,我将牢记在心,以备将来之需。
if file == nil {
    log.Println("File is nil.")
    log.Println(err)
    log.Println("*****")
    c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
        "title": "Select the input file", "error": "Please select the input file.",
    })   
    return 
}
英文:
I understand that I have made mistake with the panic handling. The validation is working if I add the return statement after the c.HTML.
This will stop the function from executing the rest of the code.
Thanks to @AlexAtNet for his advice and I will keep in mind in future.
if file == nil {
    log.Println("File is nil.")
    log.Println(err)
    log.Println("*****")
    c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
        "title": "Select the input file","error" : "Please select the input file.",
    })   
	return 
} 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论