HTTP / 1.1 206部分内容
接受范围:字节
内容长度:104715956
内容范围:字节0-104715955 / 104715956
内容类型:视频/ mp4
 http.ServeFile() HTTP 206部分内容 Content-Range 


 HTTP 206部分内容 HTTP 200 OK  HTTP 200 OK  HTTP 200 OK 

I developed a webserver using golang. Pretty plane stuff, it just provides html/js/css and images which works perfectly fine:

func main() {
    http.Handle("/", new(viewHandler))
    http.ListenAndServe(":8080", nil)
}

func (vh *viewHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    path := r.URL.Path[1:]
    log.Println(path)
    data, err := ioutil.ReadFile(string(path))

    if err == nil {

        var contentType string

        if strings.HasSuffix(path, ".html") {
            contentType = "text/html"
        } else if strings.HasSuffix(path, ".css") {
            contentType = "text/css"
        } else if strings.HasSuffix(path, ".js") {
            contentType = "application/javascript"
        } else if strings.HasSuffix(path, ".png") {
            contentType = "image/png"
        } else if strings.HasSuffix(path, ".jpg") {
            contentType = "image/jpeg"
        } 

        w.Header().Add("Content-Type", contentType)
        w.Write(data)
    } else {
        log.Println("ERROR!")
        w.WriteHeader(404)
        w.Write([]byte("404 - " + http.StatusText(404)))
    }
}

I tried to add a video in mp4 format to my website in the same way:

<video width="685" height="525" autoplay loop style="margin-top: 20px">
   <source src="../public/video/marketing.mp4" type="video/mp4">Your browser does not support the video tag.</video>

and enhanced the content type part of my go application with:

else if strings.HasSuffix(path, ".mp4") {
            contentType = "video/mp4"
        }

When I open the html file directly in Chrome the Video is playing correctly, but if I open the website by calling the Web Server at http://localhost... it can not be loaded and therefor not played.

There is no video loaded, if I try to hit it directly the browser just shows some video contols without loading the file:

Any ideas on this? thanks in advance.

UPDATE:

As suggested I also tried another video which is working perfectly fine! but I have no clue why, I compared both videos:

Could it be the size??

Cheers and thanks!

UPDATE2:

icza is right and I marked his post as correct answer to my question. But let me explain what I finally did to get it working:

I tried to solve my problem without using the http.FileServe method. Therefore I implemented like so:

} else if strings.HasSuffix(path, ".mp4") {
            contentType = "video/mp4"
            size := binary.Size(data)
            if size > 0 {
                requestedBytes := r.Header.Get("Range")
                w.Header().Add("Accept-Ranges", "bytes")
                w.Header().Add("Content-Length", strconv.Itoa(size))
                w.Header().Add("Content-Range", "bytes "+requestedBytes[6:len(requestedBytes)]+strconv.Itoa(size-1)+"/"+strconv.Itoa(size))
                w.WriteHeader(206)
            }
        }

        w.Header().Add("Content-Type", contentType)
        w.Write(data)

That worked for the first time I played the video. But since I want it to loop it should directly start from the beginning but it stuck at the very last frame of the video.

So I implemented the ServeFile() method like:

if contentType == "video/mp4" {
            http.ServeFile(w, r, path)
        } else {
            w.Header().Add("Content-Type", contentType)
            w.Write(data)
        }

The video is also playing in a loop correctly now. But I still have no idea why ServeFile() is working and the other method not though the response is exactly the same for both methods. Nevertheless the content is looking like that now:

Cheers and thanks to all of you who helped me.

Your "issue" is related to the video length / size. I don't know the default buffer Chrome uses (it may depend on multiple things like free memory, free disk space etc.), but you shouldn't rely on it for your video to play!

One of your video is a few seconds shorter and almost 3rd the size of the other. Chrome buffers completely the smaller video (likely in memory), while does not do the same with the other. And since it's bigger than the buffer, it needs the server to support Range requests (partial content serving). The way you serve the content of your video, you are not supporting partial content serving (which Chrome expects in case of "large" videos), so Chrome simply denies to handle / play the video.

http.ServeFile()

Once you do this, both your video files will play fine.

http.ServeFile()http.ServeFile()Content-Type.mp4video/mp4

Analyzing requests of a big video file

Testing this simple application:

func fileh(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "/path/to/a/big/video.mp4")    
}

func main() {
    http.HandleFunc("/", fileh)
    panic(http.ListenAndServe("localhost:8080", nil))
}
http://localhost:8080

Request #1

GET / HTTP/1.1

To get the requested (root) path.

Response #1

HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 104715956
Content-Type: video/mp4
http.ServeFile()Accept-Ranges: bytes
Accept-Ranges

Request #2

GET / HTTP/1.1
Referer: http://localhost:8080/
Range: bytes=0-

Chrome fires a Range request (asking everything from the first byte), so if your Go app does not support this, you're in trouble. See response #2.

Response #2

HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Length: 104715956
Content-Range: bytes 0-104715955/104715956
Content-Type: video/mp4
http.ServeFile()HTTP 206 Partial ContentContent-Range
HTTP 206 Partial ContentHTTP 200 OKHTTP 200 OKHTTP 200 OK

这篇关于GoLang http webserver提供视频(mp4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!