///
Search

04_File upload

Case 1

/myapp/app_test.go

package myapp import ( "encoding/json" "io/ioutil" "net/http" "net/http/httptest" "strings" "testing" "github.com/stretchr/testify/assert" ) func TestIndexPathHandler(t *testing.T) { assert := assert.New(t) res := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) mux := NewHttpHandler() mux.ServeHTTP(res, req) assert.Equal(http.StatusOK, res.Code) data, _ := ioutil.ReadAll(res.Body) assert.Equal("Hello World", string(data)) } func TestBarPathHandler_WithoutName(t *testing.T) { assert := assert.New(t) res := httptest.NewRecorder() req := httptest.NewRequest("GET", "/bar", nil) mux := NewHttpHandler() mux.ServeHTTP(res, req) assert.Equal(http.StatusOK, res.Code) data, _ := ioutil.ReadAll(res.Body) assert.Equal("Hello World!", string(data)) } func TestBarPathHandler_WithName(t *testing.T) { assert := assert.New(t) res := httptest.NewRecorder() req := httptest.NewRequest("GET", "/bar?name=tucker", nil) mux := NewHttpHandler() mux.ServeHTTP(res, req) assert.Equal(http.StatusOK, res.Code) data, _ := ioutil.ReadAll(res.Body) assert.Equal("Hello tucker!", string(data)) } func TestFooHandler_WithoutJson(t *testing.T) {//1)foo핸들러를 받아서 Json으로 변환 assert := assert.New(t)//시작하기전에 앞서서 //1-1goconvey를 실행시키고 작업을 해줘야한다. res := httptest.NewRecorder() req := httptest.NewRequest("GET", "/foo", nil)//2)입력값 없이 foo에 대해서 진행 mux := NewHttpHandler() mux.ServeHTTP(res, req) assert.Equal(http.StatusBadRequest, res.Code)//3)StatusOK->StatusBadRequest로 바꿔줘야한다. }//4)goconvey가 백그라운드에서 검사를 해준다. //5)여기서 부터는 JSON을 넣어서 한번 실습해본다. func TestFooHandler_WithJson(t *testing.T) { assert := assert.New(t) res := httptest.NewRecorder() req := httptest.NewRequest("POST", "/foo", strings.NewReader(`{"first_name":"tucker", "last_name":"kim", "email":"tucker@naver.com"}`)) mux := NewHttpHandler() mux.ServeHTTP(res, req) assert.Equal(http.StatusCreated, res.Code) //여기서 부터 user 구조체를 디코더 해주는 작업 user := new(User) err := json.NewDecoder(res.Body).Decode(user)//에러 받기 assert.Nil(err)//에러가 없어야한다. assert.Equal("tucker", user.FirstName) assert.Equal("kim", user.LastName) }
Go
복사
보충설명
1-1 : goconvey를 실행시키고 지금 할당된 포트(8080)를 접속하면 goconvey가 돌고 있는 것을 확인 할 수 있다.

/myapp/app.go

package myapp import ( "encoding/json" "fmt" "net/http" "time" ) type User struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` Email string `json:"email"` CreatedAt time.Time `json:"created_at"` } func indexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello World") } type fooHandler struct{} func (f *fooHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { user := new(User) err := json.NewDecoder(r.Body).Decode(user)//json 디코딩이 실패할 경우 err가 나온다. if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, "Bad Request: ", err) return } user.CreatedAt = time.Now() data, _ := json.Marshal(user) w.Header().Add("content-type", "application/json") w.WriteHeader(http.StatusCreated) fmt.Fprint(w, string(data)) } func barHandler(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") if name == "" { name = "World" } fmt.Fprintf(w, "Hello %s!", name) } func NewHttpHandler() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) mux.HandleFunc("/bar", barHandler) mux.Handle("/foo", &fooHandler{}) return mux }
Go
복사

/main.go

package main import ( "net/http" "github.com/GloryKim/Web_Go_Private/04_File upload/Number1/myapp" ) func main() { //http.Handle("/", http.FileServer(http.Dir("public"))) //이 경로의 파일을 오픈 http.ListenAndServe(":3000", myapp.NewHttpHandler()) }
Go
복사

Case 2

/public/index.html

<html> <head> <title>Go 로 만드는 웹 4</title> </head> <body> <p><h1>파일을 전송해보자.</h1></p> <form action="/uploads" method="POST" accept-charset="utf-8" enctype="multipart/form-data"> <p><input type="file" id="upload_file" name="upload_file"/></p> <p><input type="submit" name="upload"/></p> </form> </body> </html>
HTML
복사

/main_test.go

package main import ( "bytes" "io" "mime/multipart" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" ) func TestUploadTest(t *testing.T) { assert := assert.New(t) path := "C:/Users/tucker/Downloads/goWeb3.png" file, _ := os.Open(path) defer file.Close() os.RemoveAll("./uploads") buf := &bytes.Buffer{} writer := multipart.NewWriter(buf) multi, err := writer.CreateFormFile("upload_file", filepath.Base(path)) assert.NoError(err) io.Copy(multi, file) writer.Close() res := httptest.NewRecorder() req := httptest.NewRequest("POST", "/uploads", buf) req.Header.Set("Content-type", writer.FormDataContentType()) uploadsHandler(res, req) assert.Equal(http.StatusOK, res.Code) uploadFilePath := "./uploads/" + filepath.Base(path) _, err = os.Stat(uploadFilePath) assert.NoError(err) uploadFile, _ := os.Open(uploadFilePath) originFile, _ := os.Open(path) defer uploadFile.Close() defer originFile.Close() uploadData := []byte{} originData := []byte{} uploadFile.Read(uploadData) originFile.Read(originData) assert.Equal(originData, uploadData) }
Go
복사

/main.go

package main import ( "fmt" "net/http" "os" "io" ) func uploadsHandler(w http.ResponseWriter, r *http.Request) { uploadFile, header, err := r.FormFile("upload_file") if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, err) return } defer uploadFile.Close() dirname := "./uploads" os.MkdirAll(dirname, 0777) filepath := fmt.Sprintf("%s/%s", dirname, header.Filename) file, err := os.Create(filepath) defer file.Close() //항상 닫아줘야한다.핸들이 OS 자원인데 꼭 반납을 해줘야하기 때문 if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) return } io.Copy(file, uploadFile)//File Copy os.Copy가 아닌거 검토 w.WriteHeader(http.StatusOK) fmt.Fprint(w, filepath) } func main() { http.HandleFunc("/uploads", uploadsHandler) http.Handle("/", http.FileServer(http.Dir("public"))) http.ListenAndServe(":3000", nil) }
Go
복사