0
votes

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,

  • Content-Length
  • Content-Type
  • Accept-Ranges
  • Content-Disposition (attachment)

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?

1
i am trying now golang.org/pkg/net/http/#ServeContent method. Sample file may be not available at this moment because server rebuilding - Sashitha
still not solved - Sashitha

1 Answers

0
votes

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.