(原) 静态文件之电影播放

原创文章,请后转载,并注明出处。

这是一个电影播放的静态文件服务器,缘于那台不好安装软件的Arm Win11:不少的视频软件都不支持WinArm版。那就直接在浏览器里播放就好。而实际上有些浏览器点击就下载。

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/gorilla/mux"
)

var (
	WebServer string
	ServerDir string
)

const PlayPage = `
<!DOCTYPE html>
<html>
<style>
   *{padding:0px;margin:0px;height:100%s;}
</style>
<body>

	<video controls="controls" autoplay="autoplay">
	<source src="%s" type="video/mp4" />
	</video>

</body>
</html>
`

func Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var url string
		// 包含 /open_movie 开头,则为播放视频,直接返回静态视频文件
		if strings.HasPrefix(r.RequestURI, "/open_movie") {
			r.URL.Path = strings.Replace(r.RequestURI, "/open_movie", "", 1)
			next.ServeHTTP(w, r)
		} else {
			log.Print(r.RequestURI)
			// 视频文件结尾,则嵌入播放页面代码
			if r.TLS == nil {
				url = fmt.Sprintf("http://%s/open_movie%s", r.Host, r.RequestURI)
			} else {
				url = fmt.Sprintf("https://%s/open_movie%s", r.Host, r.RequestURI)
			}

			u := strings.ToLower(url)
			// 嵌入播放代码,支持mkv,mp4
			if strings.HasSuffix(u, ".mp4") || strings.HasSuffix(u, ".mkv") {
				fmt.Fprintf(w, fmt.Sprintf(PlayPage, "%%", url))
			} else {
				next.ServeHTTP(w, r)
			}
		}
	})
}

func init() {
	flag.StringVar(&WebServer, "w", "0.0.0.0:80", "Web服务端口")
	flag.StringVar(&ServerDir, "d", "./", "服务目录")
	flag.Parse()
}

func main() {
	r := mux.NewRouter()
	r.Use(Middleware) // 中间件

	r.Handle("/", http.FileServer(http.Dir(ServerDir)))                     // 静态文件处理
	r.Handle("/{content}", http.FileServer(http.Dir(ServerDir)))            // 静态文件处理
	r.Handle("/open_movie/{content}", http.FileServer(http.Dir(ServerDir))) // 静态文件处理

	log.Print("服务运行于 ", WebServer, " , 服务目录 ", ServerDir)
	http.ListenAndServe(WebServer, r)
}

代码很简单,也不优雅,还出现了%%的问题。先用着。


再版修改

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
)

var (
	WebServer string
	ServerDir string
	AddCode   = `
<style>
	a{font-size:22px;display:block;text-decoration:none;padding:10px;}
	.hovered {color: red;margin-left:10px;}
</style>
<script>	
	var aLinks = document.getElementsByTagName('a');  // 获取所有的<a>元素
	// 遍历<a>元素并添加事件监听器
	for (var i = 0; i < aLinks.length; i++) {
	aLinks[i].addEventListener('mouseover', function() {		
		this.classList.add('hovered'); // 鼠标移入时的处理逻辑
	});

	aLinks[i].addEventListener('mouseout', function() {		
		this.classList.remove('hovered');// 鼠标移出时的处理逻辑
	});
	}
</script>
`
	PlayPage = `
<!DOCTYPE html>
<html>
<title>文件浏览</title>
<style>
   *{ padding:0px;margin:0px;height:100%s; }
</style>
<body>
	<video controls="controls" autoplay="autoplay">
	<source src="%s" type="video/%s" />
	</video>
</body>
</html>
`
)

func Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var urlStr string
		// 包含 /open_movie 开头,则为播放视频,直接返回静态视频文件
		if strings.HasPrefix(r.RequestURI, "/open_movie") {
			r.URL.Path, _ = url.QueryUnescape(strings.Replace(r.RequestURI, "/open_movie", "", 1))
			next.ServeHTTP(w, r)
		} else {
			// 视频文件结尾,则嵌入播放页面代码
			if r.TLS == nil {
				urlStr = fmt.Sprintf("http://%s/open_movie%s", r.Host, r.RequestURI)
			} else {
				urlStr = fmt.Sprintf("https://%s/open_movie%s", r.Host, r.RequestURI)
			}
			unUrl, _ := url.QueryUnescape(urlStr)
			if strings.HasSuffix(urlStr, "favicon.ico") {
				log.Print(unUrl)
			}
			u := strings.ToLower(urlStr)
			// 嵌入播放代码,支持mkv,mp4(mkv可能存在问题)
			if strings.HasSuffix(u, ".mp4") {
				fmt.Fprintf(w, fmt.Sprintf(PlayPage, "%%", unUrl, "mp4"))
			} else if strings.HasSuffix(u, ".mkv") {
				fmt.Fprintf(w, fmt.Sprintf(PlayPage, "%%", unUrl, "mkv"))
			} else {
				next.ServeHTTP(w, r)
			}
		}
	})
}

func defaultPageHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		h.ServeHTTP(w, r)
		fmt.Fprintf(w, AddCode) // 补充代码,实现样式和一些功能
	}
}

func init() {
	flag.StringVar(&WebServer, "w", "0.0.0.0:80", "Web服务端口")
	flag.StringVar(&ServerDir, "d", "./", "服务目录")
	flag.Parse()
}

func main() {
	fs := http.FileServer(http.Dir(ServerDir))
	http.Handle("/", Middleware(defaultPageHandler(fs)))

	log.Print("服务运行于 ", WebServer, " , 服务目录 ", ServerDir)
	http.ListenAndServe(WebServer, nil)
}

相关文章