일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- perfect
- GoCD
- SWIFT
- kitura
- mysql
- rethinkdb
- PYTHON
- postgres
- sshpass
- appium server
- STF
- ssh
- ftp
- Materials
- create table
- nohup
- nGrinder
- Jupyter
- postgresql
- openpyxl
- Jupyter Notebook
- appium
- insert
- 28015
- ubuntu
- nmap
- STF_PortForwarding
- port forwarding
- centos
- 실행권한
- Today
- Total
don't stop believing
Upload files 본문
이번에는 파일 업로드를 해보겠습니다.
https://github.com/gin-gonic/gin#upload-files
파일 하나 올리는 것과, 여러개를 동시에 올리는 것을 해보겠습니다.
우선 파일을 올릴 수 있는 html 파일을 아래와 같이 만들어 줍니다. 저는 uploadfiles.html로 만들었습니다.
위치는 templates 폴더 안에 위치합니다.
<html> <head> <title>Tongchun's go gin</title> </head> <body> <h2>page: {{ .page }}</h2> <form action="http://localhost:8080/upload" method="POST" enctype="multipart/form-data"> upload file: <input type="file" name="file"> <input type="submit" value="Submit"> </form> </body> </html>
이번에는 server.go 내용입니다.
package main import ( "fmt" "log" "net/http" "path/filepath" "github.com/gin-gonic/gin" ) func setupRouter() *gin.Engine { // Disable Console Color // gin.DisableConsoleColor() r := gin.Default() r.GET("/uploadpage", func(c *gin.Context) { title := "upload single file" c.HTML(http.StatusOK, "uploadfile.html", gin.H{ "page": title, }) }) r.POST("/upload", uploadSingle) return r } func uploadSingle(c *gin.Context) { // single file file, err := c.FormFile("file") if err != nil { c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error())) return } log.Println(file.Filename) // Upload the file to specific dst. filename := filepath.Base(file.Filename) uploadPath := "./example/upload/" + filename log.Println(filename) if err := c.SaveUploadedFile(file, uploadPath); err != nil { c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error())) return } c.JSON(200, gin.H{ "status": "posted", "file name": file.Filename, }) } func main() { r := setupRouter() // Set a lower memory limit for multipart forms (default is 32 MiB) r.MaxMultipartMemory = 8 << 20 // 8 MiB r.Static("/files", "./example/upload") r.LoadHTMLGlob("./example/templates/*") // Listen and Server in 0.0.0.0:8080 r.Run(":8080") }
먼저 main() 함수에 아래와 같이 MaxMultipartMemory를 설정합니다.
// Set a lower memory limit for multipart forms (default is 32 MiB)
r.MaxMultipartMemory = 8 << 20 // 8 MiB
비트 이동과 메모리 설정의 경우 아래 포스트를 참고할 수 있습니다.
https://dejavuqa.tistory.com/328
setupRouter() 함수안에 파일 업로드를 할수 있는 GET method의 경로를 추가합니다.
r.GET("/uploadpage", func(c *gin.Context) {
title := "upload single file"
c.HTML(http.StatusOK, "uploadfile.html", gin.H{
"page": title,
})
})
server.go를 실행하고 localhost:8080/uploadpage 를 호출하면 파일을 업로드 할 수 있는 페이지가 호출됩니다.
html 페이지에서 submit 버튼을 클릭하면 loalhost:8080/upload 로 파일을 업로드 하게 됩니다.
/upload 경로의 handler 함수로 uploadSingle() 함수가 호출됩니다.
업로드된 파일은 설정된 경로에 파일 이름 그대로 저장이 됩니다.
실행해 보겠습니다.
$ go run example/server.go [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /uploadpage --> main.setupRouter.func1 (3 handlers) [GIN-debug] POST /upload --> main.uploadSingle (3 handlers) [GIN-debug] GET /files/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers) [GIN-debug] HEAD /files/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers) [GIN-debug] Loaded HTML Templates (4): - note.html - uploadfile.html - - index.html [GIN-debug] Listening and serving HTTP on :8080
localhost:8080/uploadpage 를 호출하고 업로드할 파일을 선택합니다.
Submit을 클릭해 파일을 업로드 합니다.
파일이 재대로 올라갔는지 서버에서도 확인해 봅니다.
$ ll ./example/upload/ total 37136 drwxr-xr-x 4 tongchunkim staff 128B 2 28 16:46 . drwxr-xr-x 6 tongchunkim staff 192B 2 27 16:37 .. -rw-r--r-- 1 tongchunkim staff 34K 2 28 16:46 traffic_control.zip
이번에는 파일 3개와 Post Form 데이터를 동시에 받아보겠습니다.
먼저 아래와 같이 html 파일을 수정합니다.
<html> <head> <title>Tongchun's go gin</title> </head> <body> <h2>page: {{ .page }}</h2> <form action="http://localhost:8080/multiupload" method="POST" enctype="multipart/form-data"> first name: <input type="text" name="first_name"><br> family name: <input type="text" name="family_name"><br> upload file 1: <input type="file" name="file"><br> upload file 2: <input type="file" name="file"><br> upload file 3: <input type="file" name="file"><br> <input type="submit" value="Submit"> </form> </body> </html>
확인할 사항은 file을 넘기는 input의 name을 file이라고 모두 동일하게 합니다.
그러면 3개의 file 데이터는 슬라이스 타입으로 전달되게 됩니다.
그리고 server.go 에서는 아래와 같이 route를 추가했습니다.
r.POST("/multiupload", uploadMultifile)
uploadMultifile 핸들러 함수는 아래와 같습니다.
func uploadMultifile(c *gin.Context) { firstName := c.PostForm("first_name") familyName := c.PostForm("family_name") // Multipart form form, err := c.MultipartForm() if err != nil { c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error())) return } files := form.File["file"] log.Println(form) for _, file := range files { log.Println(file.Filename) // Upload the file to specific dst. filename := filepath.Base(file.Filename) uploadPath := "./example/upload/" + filename // Upload the file to specific dst. if err := c.SaveUploadedFile(file, uploadPath); err != nil { c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error())) return } } c.JSON(200, gin.H{ "status": "posted", "file lise": files, "file count": len(files), "first name": firstName, "family name": familyName, }) }
server.go를 실행합니다.
$ go run example/server.go [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /uploadpage --> main.setupRouter.func1 (3 handlers) [GIN-debug] POST /upload --> main.uploadSingle (3 handlers) [GIN-debug] POST /multiupload --> main.uploadMultifile (3 handlers) [GIN-debug] GET /files/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers) [GIN-debug] HEAD /files/*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers) [GIN-debug] Loaded HTML Templates (4): - index.html - note.html - uploadfile.html - [GIN-debug] Listening and serving HTTP on :8080
uploadpage를 열고 post 데이터와 파일을 선택합니다.
submit을 클릭하면 지정한 json 데이터가 리턴됩니다.
지정된 경로에는 파일이 업로드되어 있습니다.
ll ./example/upload/ total 2056 drwxr-xr-x 6 tongchunkim staff 192B 2 28 18:28 . drwxr-xr-x 6 tongchunkim staff 192B 2 27 16:37 .. -rw-r--r-- 1 tongchunkim staff 34K 2 28 16:46 traffic_control.zip -rw-r--r-- 1 tongchunkim staff 321K 2 28 18:28 스크린샷 2019-02-28 오후 4.45.41.png -rw-r--r-- 1 tongchunkim staff 310K 2 28 18:28 스크린샷 2019-02-28 오후 4.46.50.png -rw-r--r-- 1 tongchunkim staff 356K 2 28 18:28 스크린샷 2019-02-28 오후 6.00.06.png
추가로 main() 함수에는 Static file 경로를 지정했습니다.
r.Static("/files", "./example/upload")
localhost:8080/files/ 하위 경로에 업로드한 파일을 추가하면 다운받을 수 있습니다.
http://localhost:8080/multiupload/traffic_control.zip
Gin을 이용한 파일 업로드였습니다.
'Golang > Gin' 카테고리의 다른 글
[swag] Gin에서 Swagger 사용하기 (0) | 2019.03.04 |
---|---|
Grouping routes (0) | 2019.03.04 |
Map as querystring or postform parameters (0) | 2019.02.27 |
Another example: query + post form (0) | 2019.02.15 |
Multipart/Urlencoded Form (1) | 2019.02.14 |