forked from mirror/gin
Merge pull request #775 from gin-gonic/upload
Support upload single or multiple files.
This commit is contained in:
commit
df2e95cc78
20
context.go
20
context.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
"mime/multipart"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -30,7 +31,10 @@ const (
|
||||||
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
|
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
|
||||||
)
|
)
|
||||||
|
|
||||||
const abortIndex int8 = math.MaxInt8 / 2
|
const (
|
||||||
|
defaultMemory = 32 << 20 // 32 MB
|
||||||
|
abortIndex int8 = math.MaxInt8 / 2
|
||||||
|
)
|
||||||
|
|
||||||
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
||||||
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
||||||
|
@ -291,7 +295,7 @@ func (c *Context) PostFormArray(key string) []string {
|
||||||
func (c *Context) GetPostFormArray(key string) ([]string, bool) {
|
func (c *Context) GetPostFormArray(key string) ([]string, bool) {
|
||||||
req := c.Request
|
req := c.Request
|
||||||
req.ParseForm()
|
req.ParseForm()
|
||||||
req.ParseMultipartForm(32 << 20) // 32 MB
|
req.ParseMultipartForm(defaultMemory)
|
||||||
if values := req.PostForm[key]; len(values) > 0 {
|
if values := req.PostForm[key]; len(values) > 0 {
|
||||||
return values, true
|
return values, true
|
||||||
}
|
}
|
||||||
|
@ -303,6 +307,18 @@ func (c *Context) GetPostFormArray(key string) ([]string, bool) {
|
||||||
return []string{}, false
|
return []string{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormFile returns the first file for the provided form key.
|
||||||
|
func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
|
||||||
|
_, fh, err := c.Request.FormFile(name)
|
||||||
|
return fh, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultipartForm is the parsed multipart form, including file uploads.
|
||||||
|
func (c *Context) MultipartForm() (*multipart.Form, error) {
|
||||||
|
err := c.Request.ParseMultipartForm(defaultMemory)
|
||||||
|
return c.Request.MultipartForm, err
|
||||||
|
}
|
||||||
|
|
||||||
// Bind checks the Content-Type to select a binding engine automatically,
|
// Bind checks the Content-Type to select a binding engine automatically,
|
||||||
// Depending the "Content-Type" header different bindings are used:
|
// Depending the "Content-Type" header different bindings are used:
|
||||||
// "application/json" --> JSON binding
|
// "application/json" --> JSON binding
|
||||||
|
|
|
@ -53,6 +53,37 @@ func must(err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContextFormFile(t *testing.T) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
mw := multipart.NewWriter(buf)
|
||||||
|
w, err := mw.CreateFormFile("file", "test")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
w.Write([]byte("test"))
|
||||||
|
}
|
||||||
|
mw.Close()
|
||||||
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||||
|
c.Request, _ = http.NewRequest("POST", "/", buf)
|
||||||
|
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
|
||||||
|
f, err := c.FormFile("file")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "test", f.Filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContextMultipartForm(t *testing.T) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
mw := multipart.NewWriter(buf)
|
||||||
|
mw.WriteField("foo", "bar")
|
||||||
|
mw.Close()
|
||||||
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||||
|
c.Request, _ = http.NewRequest("POST", "/", buf)
|
||||||
|
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
|
||||||
|
f, err := c.MultipartForm()
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotNil(t, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextReset(t *testing.T) {
|
func TestContextReset(t *testing.T) {
|
||||||
router := New()
|
router := New()
|
||||||
c := router.allocateContext()
|
c := router.allocateContext()
|
||||||
|
|
Loading…
Reference in New Issue