Explorar el Código

feat(context): add SaveUploadedFile func. (#1022)

* feat(context): add SaveUploadedFile func.

* feat(context): update multiple upload examples.

* style(example): fix gofmt

* fix(example): add missing return
Eason Lin hace 8 años
padre
commit
93b3a0d7ec
Se han modificado 5 ficheros con 72 adiciones y 35 borrados
  1. 7 1
      README.md
  2. 19 0
      context.go
  3. 42 0
      context_test.go
  4. 2 18
      examples/upload-file/multiple/main.go
  5. 2 16
      examples/upload-file/single/main.go

+ 7 - 1
README.md

@@ -275,7 +275,10 @@ func main() {
 		// single file
 		// single file
 		file, _ := c.FormFile("file")
 		file, _ := c.FormFile("file")
 		log.Println(file.Filename)
 		log.Println(file.Filename)
-
+        
+        // Upload the file to specific dst.
+        // c.SaveUploadedFile(file, dst)       
+		
 		c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
 		c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
 	})
 	})
 	router.Run(":8080")
 	router.Run(":8080")
@@ -304,6 +307,9 @@ func main() {
 
 
 		for _, file := range files {
 		for _, file := range files {
 			log.Println(file.Filename)
 			log.Println(file.Filename)
+			
+			// Upload the file to specific dst.
+            // c.SaveUploadedFile(file, dst)       
 		}
 		}
 		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
 		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
 	})
 	})

+ 19 - 0
context.go

@@ -13,6 +13,7 @@ import (
 	"net"
 	"net"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
+	"os"
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
@@ -431,6 +432,24 @@ func (c *Context) MultipartForm() (*multipart.Form, error) {
 	return c.Request.MultipartForm, err
 	return c.Request.MultipartForm, err
 }
 }
 
 
+// SaveUploadedFile uploads the form file to specific dst.
+func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
+	src, err := file.Open()
+	if err != nil {
+		return err
+	}
+	defer src.Close()
+
+	out, err := os.Create(dst)
+	if err != nil {
+		return err
+	}
+	defer out.Close()
+
+	io.Copy(out, src)
+	return nil
+}
+
 // 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

+ 42 - 0
context_test.go

@@ -72,12 +72,18 @@ func TestContextFormFile(t *testing.T) {
 	if assert.NoError(t, err) {
 	if assert.NoError(t, err) {
 		assert.Equal(t, "test", f.Filename)
 		assert.Equal(t, "test", f.Filename)
 	}
 	}
+
+	assert.NoError(t, c.SaveUploadedFile(f, "test"))
 }
 }
 
 
 func TestContextMultipartForm(t *testing.T) {
 func TestContextMultipartForm(t *testing.T) {
 	buf := new(bytes.Buffer)
 	buf := new(bytes.Buffer)
 	mw := multipart.NewWriter(buf)
 	mw := multipart.NewWriter(buf)
 	mw.WriteField("foo", "bar")
 	mw.WriteField("foo", "bar")
+	w, err := mw.CreateFormFile("file", "test")
+	if assert.NoError(t, err) {
+		w.Write([]byte("test"))
+	}
 	mw.Close()
 	mw.Close()
 	c, _ := CreateTestContext(httptest.NewRecorder())
 	c, _ := CreateTestContext(httptest.NewRecorder())
 	c.Request, _ = http.NewRequest("POST", "/", buf)
 	c.Request, _ = http.NewRequest("POST", "/", buf)
@@ -86,6 +92,42 @@ func TestContextMultipartForm(t *testing.T) {
 	if assert.NoError(t, err) {
 	if assert.NoError(t, err) {
 		assert.NotNil(t, f)
 		assert.NotNil(t, f)
 	}
 	}
+
+	assert.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test"))
+}
+
+func TestSaveUploadedOpenFailed(t *testing.T) {
+	buf := new(bytes.Buffer)
+	mw := multipart.NewWriter(buf)
+	mw.Close()
+
+	c, _ := CreateTestContext(httptest.NewRecorder())
+	c.Request, _ = http.NewRequest("POST", "/", buf)
+	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
+
+	f := &multipart.FileHeader{
+		Filename: "file",
+	}
+	assert.Error(t, c.SaveUploadedFile(f, "test"))
+}
+
+func TestSaveUploadedCreateFailed(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)
+	}
+
+	assert.Error(t, c.SaveUploadedFile(f, "/"))
 }
 }
 
 
 func TestContextReset(t *testing.T) {
 func TestContextReset(t *testing.T) {

+ 2 - 18
examples/upload-file/multiple/main.go

@@ -2,9 +2,7 @@ package main
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io"
 	"net/http"
 	"net/http"
-	"os"
 
 
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 )
 )
@@ -25,24 +23,10 @@ func main() {
 		files := form.File["files"]
 		files := form.File["files"]
 
 
 		for _, file := range files {
 		for _, file := range files {
-			// Source
-			src, err := file.Open()
-			if err != nil {
-				c.String(http.StatusBadRequest, fmt.Sprintf("file open err: %s", err.Error()))
+			if err := c.SaveUploadedFile(file, file.Filename); err != nil {
+				c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
 				return
 				return
 			}
 			}
-			defer src.Close()
-
-			// Destination
-			dst, err := os.Create(file.Filename)
-			if err != nil {
-				c.String(http.StatusBadRequest, fmt.Sprintf("Create file err: %s", err.Error()))
-				return
-			}
-			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))
 		c.String(http.StatusOK, fmt.Sprintf("Uploaded successfully %d files with fields name=%s and email=%s.", len(files), name, email))

+ 2 - 16
examples/upload-file/single/main.go

@@ -2,9 +2,7 @@ package main
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io"
 	"net/http"
 	"net/http"
-	"os"
 
 
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 )
 )
@@ -22,23 +20,11 @@ func main() {
 			c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
 			c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
 			return
 			return
 		}
 		}
-		src, err := file.Open()
-		if err != nil {
-			c.String(http.StatusBadRequest, fmt.Sprintf("file open err: %s", err.Error()))
-			return
-		}
-		defer src.Close()
 
 
-		// Destination
-		dst, err := os.Create(file.Filename)
-		if err != nil {
-			c.String(http.StatusBadRequest, fmt.Sprintf("Create file err: %s", err.Error()))
+		if err := c.SaveUploadedFile(file, file.Filename); err != nil {
+			c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
 			return
 			return
 		}
 		}
-		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))
 		c.String(http.StatusOK, fmt.Sprintf("File %s uploaded successfully with fields name=%s and email=%s.", file.Filename, name, email))
 	})
 	})