diff --git a/context.go b/context.go index 139c1864..76afb229 100644 --- a/context.go +++ b/context.go @@ -3,12 +3,15 @@ package echo import ( "encoding/json" "encoding/xml" + "io" "net/http" "fmt" "net/url" + "os" + "golang.org/x/net/websocket" ) @@ -163,6 +166,21 @@ func (c *Context) XML(code int, i interface{}) error { return xml.NewEncoder(c.response).Encode(i) } +// File sends a file as attachment. +func (c *Context) File(name string) error { + file, err := os.Open(name) + if err != nil { + return err + } + fi, err := file.Stat() + if err != nil { + return err + } + c.response.Header().Set(ContentDisposition, "attachment; filename="+fi.Name()) + _, err = io.Copy(c.response, file) + return err +} + // NoContent sends a response with no body and a status code. func (c *Context) NoContent(code int) error { c.response.WriteHeader(code) diff --git a/context_test.go b/context_test.go index 4a3bde0c..21472d3e 100644 --- a/context_test.go +++ b/context_test.go @@ -88,7 +88,6 @@ func TestContext(t *testing.T) { assert.Error(t, err) // JSON - req.Header.Set(Accept, ApplicationJSON) rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.JSON(http.StatusOK, user{"1", "Joe"}) @@ -99,7 +98,6 @@ func TestContext(t *testing.T) { } // JSONP - req.Header.Set(Accept, ApplicationJavaScript) rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) callback := "callback" @@ -111,7 +109,6 @@ func TestContext(t *testing.T) { } // XML - req.Header.Set(Accept, ApplicationXML) rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.XML(http.StatusOK, user{"1", "Joe"}) @@ -122,7 +119,6 @@ func TestContext(t *testing.T) { } // String - req.Header.Set(Accept, TextPlain) rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.String(http.StatusOK, "Hello, World!") @@ -133,7 +129,6 @@ func TestContext(t *testing.T) { } // HTML - req.Header.Set(Accept, TextHTML) rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.HTML(http.StatusOK, "Hello, World!") @@ -143,6 +138,15 @@ func TestContext(t *testing.T) { assert.Equal(t, "Hello, World!", rec.Body.String()) } + // File + rec = httptest.NewRecorder() + c = NewContext(req, NewResponse(rec), New()) + err = c.File("test/fixture/walle.png") + if assert.NoError(t, err) { + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, 219885, rec.Body.Len()) + } + // NoContent rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) diff --git a/echo.go b/echo.go index 5b1e5967..2d66ec5b 100644 --- a/echo.go +++ b/echo.go @@ -64,6 +64,11 @@ type ( binder struct { } + // Validator is the interface that wraps the Validate method. + Validator interface { + Validate() error + } + // Renderer is the interface that wraps the Render method. Renderer interface { Render(w io.Writer, name string, data interface{}) error @@ -119,7 +124,6 @@ const ( // Headers //--------- - Accept = "Accept" AcceptEncoding = "Accept-Encoding" Authorization = "Authorization" ContentDisposition = "Content-Disposition" @@ -587,7 +591,7 @@ func wrapHandler(h Handler) HandlerFunc { } } -func (*binder) Bind(r *http.Request, i interface{}) (err error) { +func (binder) Bind(r *http.Request, i interface{}) (err error) { ct := r.Header.Get(ContentType) err = UnsupportedMediaType if strings.HasPrefix(ct, ApplicationJSON) { diff --git a/test/fixture/walle.png b/test/fixture/walle.png new file mode 100644 index 00000000..493985d4 Binary files /dev/null and b/test/fixture/walle.png differ