Serve large files

682 views
Skip to first unread message

Jeffrey Smith

unread,
Feb 28, 2017, 6:13:20 AM2/28/17
to golang-nuts
I'm trying to server up a file that can be very large so would like to try and stream the content back.

package main

import (
        "bytes"
        "fmt"
        //"io"
        "io/ioutil"
        "log"
        "net/http"
)

func main() {

        http.HandleFunc("/", serverFile)
        if err := http.ListenAndServe(":8085", nil); err != nil {
                log.Fatal(err)
        }

}

func serverFile(w http.ResponseWriter, r *http.Request) {

        streamPDFbytes, err := ioutil.ReadFile("./large.txt")
        if err != nil {
                fmt.Println(err)
                return
        }

        b := bytes.NewBuffer(streamPDFbytes)

        w.Header().Set("Content-Disposition", "attachment;filename=large.txt")
        //io.Copy(w, b)
        if _, err := b.WriteTo(w); err != nil {
                fmt.Fprintf(w, "%s", err)
        }
}

I tried using this but I believe ioutil.readFile actually calls ioutil.readAll so sticks the whole content of the file into a byte array. What am i doing wrong?

Jordan Krage

unread,
Feb 28, 2017, 6:34:04 AM2/28/17
to golang-nuts
Try using os.Open to get a *File (which implements io.Reader), and then io.Copy to the response from the file.

Jeffrey Smith

unread,
Feb 28, 2017, 7:05:19 AM2/28/17
to golang-nuts
Works perfectly. cheers

package main

import (
        "fmt"
        "io"
        "log"
        "net/http"
        "os"
)

func main() {

        http.HandleFunc("/", serverFile)
        if err := http.ListenAndServe(":8085", nil); err != nil {
                log.Fatal(err)
        }

}

func serverFile(w http.ResponseWriter, r *http.Request) {

        streamPDFbytes, err := os.Open("./large.txt")
        if err != nil {
                fmt.Println(err)
                return
        }

        w.Header().Set("Content-Disposition", "attachment;filename=large.txt")
        io.Copy(w, streamPDFbytes)
}

Christian Joergensen

unread,
Feb 28, 2017, 7:19:10 AM2/28/17
to golang-nuts
Hello,

I'd recommend you take a look at:

This also gives you support for range requests and other goodies.

Cheers,

Christian

Jesse McNelis

unread,
Feb 28, 2017, 7:19:13 AM2/28/17
to golang-nuts
Try using os.Open to get a *File (which implements io.Reader), and then io.Copy to the response from the file.

You should use https://golang.org/pkg/net/http/#ServeFile that's what it does. It will also handle requests with range headers for allowing the client to fetch just a part of the file.


Tamás Gulácsi

unread,
Feb 28, 2017, 8:12:52 AM2/28/17
to golang-nuts
A "defer streamPDFbytes.Close()" is missing - you'll run out of file descriptors...
Reply all
Reply to author
Forward
0 new messages