98
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								README.md
									
									
									
									
									
								
							| @ -111,7 +111,7 @@ BenchmarkZeus_GithubAll 		| 2000 		| 944234 	| 300688 	| 2648 | |||||||
|  |  | ||||||
| ## API Examples | ## API Examples | ||||||
|  |  | ||||||
| #### Using GET, POST, PUT, PATCH, DELETE and OPTIONS | ### Using GET, POST, PUT, PATCH, DELETE and OPTIONS | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| @ -137,7 +137,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Parameters in path | ### Parameters in path | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| @ -162,7 +162,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Querystring parameters | ### Querystring parameters | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| 	router := gin.Default() | 	router := gin.Default() | ||||||
| @ -229,34 +229,66 @@ func main() { | |||||||
| id: 1234; page: 1; name: manu; message: this_is_great | id: 1234; page: 1; name: manu; message: this_is_great | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Another example: upload file | ### Upload files | ||||||
|  |  | ||||||
| References issue [#548](https://github.com/gin-gonic/gin/issues/548). | #### Single file | ||||||
|  |  | ||||||
|  | References issue [#774](https://github.com/gin-gonic/gin/issues/774) and detail [example code](examples/upload-file/single). | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| 	router := gin.Default() | 	router := gin.Default() | ||||||
|  |  | ||||||
| 	router.POST("/upload", func(c *gin.Context) { | 	router.POST("/upload", func(c *gin.Context) { | ||||||
|  | 		// single file | ||||||
|  | 		file, _ := c.FormFile("file") | ||||||
|  | 		log.Println(file.Filename) | ||||||
|  |  | ||||||
| 	        file, header , err := c.Request.FormFile("upload") | 		c.String(http.StatusOK, fmt.Printf("'%s' uploaded!", file.Filename)) | ||||||
| 	        filename := header.Filename |  | ||||||
| 	        fmt.Println(header.Filename) |  | ||||||
| 	        out, err := os.Create("./tmp/"+filename+".png") |  | ||||||
| 	        if err != nil { |  | ||||||
| 	            log.Fatal(err) |  | ||||||
| 	        } |  | ||||||
| 	        defer out.Close() |  | ||||||
| 	        _, err = io.Copy(out, file) |  | ||||||
| 	        if err != nil { |  | ||||||
| 	            log.Fatal(err) |  | ||||||
| 	        }    |  | ||||||
| 	}) | 	}) | ||||||
| 	router.Run(":8080") | 	router.Run(":8080") | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Grouping routes | How to `curl`: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | curl -X POST http://localhost:8080/upload \ | ||||||
|  |   -F "file=@/Users/appleboy/test.zip" \ | ||||||
|  |   -H "Content-Type: multipart/form-data" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Multiple files | ||||||
|  |  | ||||||
|  | See the detail [example code](examples/upload-file/multiple). | ||||||
|  |  | ||||||
|  | ```go | ||||||
|  | func main() { | ||||||
|  | 	router := gin.Default() | ||||||
|  | 	router.POST("/upload", func(c *gin.Context) { | ||||||
|  | 		// Multipart form | ||||||
|  | 		form, _ := c.MultipartForm() | ||||||
|  | 		files := form.File["upload[]"] | ||||||
|  |  | ||||||
|  | 		for _, file := range files { | ||||||
|  | 			log.Println(file.Filename) | ||||||
|  | 		} | ||||||
|  | 		c.String(http.StatusOK, fmt.Printf("%d files uploaded!", len(files))) | ||||||
|  | 	}) | ||||||
|  | 	router.Run(":8080") | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | How to `curl`: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | curl -X POST http://localhost:8080/upload \ | ||||||
|  |   -F "upload[]=@/Users/appleboy/test1.zip" \ | ||||||
|  |   -F "upload[]=@/Users/appleboy/test2.zip" \ | ||||||
|  |   -H "Content-Type: multipart/form-data" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Grouping routes | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| 	router := gin.Default() | 	router := gin.Default() | ||||||
| @ -282,7 +314,7 @@ func main() { | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Blank Gin without middleware by default | ### Blank Gin without middleware by default | ||||||
|  |  | ||||||
| Use | Use | ||||||
|  |  | ||||||
| @ -296,7 +328,7 @@ r := gin.Default() | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Using middleware | ### Using middleware | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| 	// Creates a router without any middleware by default | 	// Creates a router without any middleware by default | ||||||
| @ -331,7 +363,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Model binding and validation | ### Model binding and validation | ||||||
|  |  | ||||||
| To bind a request body into a type, use model binding. We currently support binding of JSON, XML and standard form values (foo=bar&boo=baz). | To bind a request body into a type, use model binding. We currently support binding of JSON, XML and standard form values (foo=bar&boo=baz). | ||||||
|  |  | ||||||
| @ -381,7 +413,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Bind Query String | ### Bind Query String | ||||||
|  |  | ||||||
| See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292). | See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292). | ||||||
|  |  | ||||||
| @ -457,7 +489,7 @@ $ curl -v --form user=user --form password=password http://localhost:8080/login | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| #### XML, JSON and YAML rendering | ### XML, JSON and YAML rendering | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| @ -496,7 +528,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ####Serving static files | ### Serving static files | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func main() { | func main() { | ||||||
| @ -510,7 +542,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ####HTML rendering | ### HTML rendering | ||||||
|  |  | ||||||
| Using LoadHTMLGlob() or LoadHTMLFiles() | Using LoadHTMLGlob() or LoadHTMLFiles() | ||||||
|  |  | ||||||
| @ -590,7 +622,7 @@ func main() { | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Redirects | ### Redirects | ||||||
|  |  | ||||||
| Issuing a HTTP redirect is easy: | Issuing a HTTP redirect is easy: | ||||||
|  |  | ||||||
| @ -602,7 +634,7 @@ r.GET("/test", func(c *gin.Context) { | |||||||
| Both internal and external locations are supported. | Both internal and external locations are supported. | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Custom Middleware | ### Custom Middleware | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| func Logger() gin.HandlerFunc { | func Logger() gin.HandlerFunc { | ||||||
| @ -642,7 +674,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Using BasicAuth() middleware | ### Using BasicAuth() middleware | ||||||
| ```go | ```go | ||||||
| // simulate some private data | // simulate some private data | ||||||
| var secrets = gin.H{ | var secrets = gin.H{ | ||||||
| @ -681,7 +713,7 @@ func main() { | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Goroutines inside a middleware | ### Goroutines inside a middleware | ||||||
| When starting inside a middleware or handler, you **SHOULD NOT** use the original context inside it, you have to use a read-only copy. | When starting inside a middleware or handler, you **SHOULD NOT** use the original context inside it, you have to use a read-only copy. | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| @ -713,7 +745,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Custom HTTP configuration | ### Custom HTTP configuration | ||||||
|  |  | ||||||
| Use `http.ListenAndServe()` directly, like this: | Use `http.ListenAndServe()` directly, like this: | ||||||
|  |  | ||||||
| @ -740,7 +772,7 @@ func main() { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Graceful restart or stop | ### Graceful restart or stop | ||||||
|  |  | ||||||
| Do you want to graceful restart or stop your web server? | Do you want to graceful restart or stop your web server? | ||||||
| There are some ways this can be done. | There are some ways this can be done. | ||||||
| @ -771,7 +803,7 @@ An alternative to endless: | |||||||
|   - You should add/modify tests to cover your proposed code changes. |   - You should add/modify tests to cover your proposed code changes. | ||||||
|   - If your pull request contains a new feature, please document it on the README. |   - If your pull request contains a new feature, please document it on the README. | ||||||
|  |  | ||||||
| ## Example | ## Users | ||||||
|  |  | ||||||
| Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework. | Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework. | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								examples/upload-file/multiple/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								examples/upload-file/multiple/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/gin-gonic/gin" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	router := gin.Default() | ||||||
|  | 	router.Static("/", "./public") | ||||||
|  | 	router.POST("/upload", func(c *gin.Context) { | ||||||
|  | 		name := c.PostForm("name") | ||||||
|  | 		email := c.PostForm("email") | ||||||
|  |  | ||||||
|  | 		// Multipart form | ||||||
|  | 		form, _ := c.MultipartForm() | ||||||
|  | 		files := form.File["files"] | ||||||
|  |  | ||||||
|  | 		for _, file := range files { | ||||||
|  | 			// Source | ||||||
|  | 			src, _ := file.Open() | ||||||
|  | 			defer src.Close() | ||||||
|  |  | ||||||
|  | 			// Destination | ||||||
|  | 			dst, _ := os.Create(file.Filename) | ||||||
|  | 			defer dst.Close() | ||||||
|  |  | ||||||
|  | 			// Copy | ||||||
|  | 			io.Copy(dst, src) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		c.String(http.StatusOK, fmt.Sprintf("Uploaded successfully %d files with fields name=%s and email=%s.", len(files), name, email)) | ||||||
|  | 	}) | ||||||
|  | 	router.Run(":8080") | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								examples/upload-file/multiple/public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								examples/upload-file/multiple/public/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | <!doctype html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  |     <meta charset="utf-8"> | ||||||
|  |     <title>Multiple file upload</title> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | <h1>Upload multiple files with fields</h1> | ||||||
|  |  | ||||||
|  | <form action="/upload" method="post" enctype="multipart/form-data"> | ||||||
|  |     Name: <input type="text" name="name"><br> | ||||||
|  |     Email: <input type="email" name="email"><br> | ||||||
|  |     Files: <input type="file" name="files" multiple><br><br> | ||||||
|  |     <input type="submit" value="Submit"> | ||||||
|  | </form> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										34
									
								
								examples/upload-file/single/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								examples/upload-file/single/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/gin-gonic/gin" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	router := gin.Default() | ||||||
|  | 	router.Static("/", "./public") | ||||||
|  | 	router.POST("/upload", func(c *gin.Context) { | ||||||
|  | 		name := c.PostForm("name") | ||||||
|  | 		email := c.PostForm("email") | ||||||
|  |  | ||||||
|  | 		// Source | ||||||
|  | 		file, _ := c.FormFile("file") | ||||||
|  | 		src, _ := file.Open() | ||||||
|  | 		defer src.Close() | ||||||
|  |  | ||||||
|  | 		// Destination | ||||||
|  | 		dst, _ := os.Create(file.Filename) | ||||||
|  | 		defer dst.Close() | ||||||
|  |  | ||||||
|  | 		// Copy | ||||||
|  | 		io.Copy(dst, src) | ||||||
|  |  | ||||||
|  | 		c.String(http.StatusOK, fmt.Sprintf("File %s uploaded successfully with fields name=%s and email=%s.", file.Filename, name, email)) | ||||||
|  | 	}) | ||||||
|  | 	router.Run(":8080") | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								examples/upload-file/single/public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/upload-file/single/public/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | <!doctype html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  |     <meta charset="utf-8"> | ||||||
|  |     <title>Single file upload</title> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | <h1>Upload single file with fields</h1> | ||||||
|  |  | ||||||
|  | <form action="/upload" method="post" enctype="multipart/form-data"> | ||||||
|  |     Name: <input type="text" name="name"><br> | ||||||
|  |     Email: <input type="email" name="email"><br> | ||||||
|  |     Files: <input type="file" name="file"><br><br> | ||||||
|  |     <input type="submit" value="Submit"> | ||||||
|  | </form> | ||||||
|  | </body> | ||||||
		Reference in New Issue
	
	Block a user