Merge pull request #784 from gin-gonic/readme

Add upload file example.
This commit is contained in:
Javier Provecho Fernandez 2017-01-03 17:04:59 +01:00 committed by GitHub
commit cc2b75f830
5 changed files with 171 additions and 33 deletions

View File

@ -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.

View 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")
}

View 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>

View 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")
}

View 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>