github.com/segakazzz/buffalo@v0.16.22-0.20210119082501-1f52048d3feb/render/download.go (about) 1 package render 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "mime" 8 "net/http" 9 "path/filepath" 10 "strconv" 11 ) 12 13 type downloadRenderer struct { 14 ctx context.Context 15 name string 16 reader io.Reader 17 } 18 19 func (r downloadRenderer) ContentType() string { 20 ext := filepath.Ext(r.name) 21 t := mime.TypeByExtension(ext) 22 if t == "" { 23 t = "application/octet-stream" 24 } 25 26 return t 27 } 28 29 func (r downloadRenderer) Render(w io.Writer, d Data) error { 30 written, err := io.Copy(w, r.reader) 31 if err != nil { 32 return err 33 } 34 35 ctx, ok := r.ctx.(responsible) 36 if !ok { 37 return fmt.Errorf("context has no response writer") 38 } 39 40 header := ctx.Response().Header() 41 disposition := fmt.Sprintf("attachment; filename=%s", r.name) 42 header.Add("Content-Disposition", disposition) 43 contentLength := strconv.Itoa(int(written)) 44 header.Add("Content-Length", contentLength) 45 46 return nil 47 } 48 49 // Download renders a file attachment automatically setting following headers: 50 // 51 // Content-Type 52 // Content-Length 53 // Content-Disposition 54 // 55 // Content-Type is set using mime#TypeByExtension with the filename's extension. Content-Type will default to 56 // application/octet-stream if using a filename with an unknown extension. 57 func Download(ctx context.Context, name string, r io.Reader) Renderer { 58 return downloadRenderer{ 59 ctx: ctx, 60 name: name, 61 reader: r, 62 } 63 } 64 65 // Download renders a file attachment automatically setting following headers: 66 // 67 // Content-Type 68 // Content-Length 69 // Content-Disposition 70 // 71 // Content-Type is set using mime#TypeByExtension with the filename's extension. Content-Type will default to 72 // application/octet-stream if using a filename with an unknown extension. 73 func (e *Engine) Download(ctx context.Context, name string, r io.Reader) Renderer { 74 return Download(ctx, name, r) 75 } 76 77 type responsible interface { 78 Response() http.ResponseWriter 79 }