Sashitha
Sashitha

Reputation: 1

Golang http serve file - giving parallel download support - contentLength & accept ranges not working

Very new to GoLang, less than 10 days. I have a http server & i need to http serve files which are inside disk. Here in default this is using "net/http" http.ServeFile(w, r, file). My problem is when i downloading these files, they don't have file pause/resume support but just downloading without showing total size. I tried adding "Content-Length" header & "Accept-Ranges" header. But seems not working.

Http Headers i worrying about are,

I have path to file, info FileInfo, w http.ResponseWriter, r http.Request before serving function.First I tried adding

w.Header().Set("Accept-Ranges", "bytes")
if w.Header().Get("Content-Encoding") == "" {
     w.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10))
}

to

func (s *Server) serveFiles(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/download/") {
    url := strings.TrimPrefix(r.URL.Path, "/download/")
    //dldir is absolute
    dldir := s.state.Config.DownloadDirectory
    file := filepath.Join(dldir, url)
    //only allow fetches/deletes inside the dl dir
    if !strings.HasPrefix(file, dldir) || dldir == file {
        http.Error(w, "Nice try\n"+dldir+"\n"+file, http.StatusBadRequest)
        return
    }
    info, err := os.Stat(file)
    if err != nil {
        http.Error(w, "File stat error: "+err.Error(), http.StatusBadRequest)
        return
    }
    switch r.Method {
    case "GET":
        if info.IsDir() {
            w.Header().Set("Content-Type", "application/zip")
            w.WriteHeader(200)
            //write .zip archive directly into response
            a := archive.NewZipWriter(w)
            a.AddDir(file)
            a.Close()
        } else {
            w.Header().Set("Accept-Ranges", "bytes")
            if w.Header().Get("Content-Encoding") == "" {
                w.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10))
            }
            http.ServeFile(w, r, file)
        }

Then i can still see it is downloading without showing total size, doesn't have pause/resume support. i tried to download files from

sample small file: https://s2.torrentfast.net/download/Dracula.2020.S01E01.HDTV.x264-PHOENiX[TGx]/[TGx]Downloaded%20from%20torrentgalaxy.to%20.txt

sample big fig: https://s2.torrentfast.net/download/Need%20For%20Speed%20Most%20Wanted%20Black%20Edition%20repack%20Mr%20DJ/Setup-1.bin

Http Get request response headers(sample small file) screenshot link

Can help?

Upvotes: 0

Views: 2544

Answers (1)

eudore
eudore

Reputation: 753

w.Header().Set("Accept-Ranges", "bytes") is not required because Range will set http.ServeFile when responding.

w.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10)) is wrong, may respond to transmission, and http.ServerFile will set this header.

The meaning of Content-Length is to specify the length of the body, and Content-Range will record the section of the transmission range and the total length information. The correct method is to use http.ServeFile to send the file directly. The ServeFile function will automatically handle the situation of Range and Cache.

Just look at the source code of net/http/fs.go.

Upvotes: 0

Related Questions