大文件转HTTP下载服务 #
单文件 #
任何文件都可以视频、音频、zip
原生 go 的实现 #
func TestDownloadFileByHttp(t *testing.T) {
fp := "./samples/1.mp4"
name := filepath.Base(fp)
http.HandleFunc("/"+name, func(writer http.ResponseWriter, request *http.Request) {
http.ServeFile(writer, request, fp)
})
err := http.ListenAndServe(":8100", nil)
assert.NoError(t, err)
}
访问地址:
http://127.0.0.1:8100/1.mp4
Kratos 或者 Gin 实现 #
所有的http服务都包装了 http.HandleFunc 你一定可以找到一个response和request,套用即可。
func TestDownloadFileByGin(t *testing.T) {
fp := "./samples/1.mp4"
name := filepath.Base(fp)
g := gin.Default()
g.GET("/"+name, func(context *gin.Context) {
http.ServeFile(context.Writer, context.Request, fp)
})
g.StaticFile("/sf_"+name, fp)
err := g.Run(":8100")
err = http.ListenAndServe(":8100", nil)
assert.NoError(t, err)
}
访问地址
http://127.0.0.1:8100/1.mp4
http://127.0.0.1:8100/sf_1.mp4
单文件数据流方式 #
func TestDownloadFileStreamByHttp(t *testing.T) {
fp := "./samples/1.mp4"
name := filepath.Base(fp)
http.HandleFunc("/"+name, func(writer http.ResponseWriter, request *http.Request) {
f, _ := os.Open(fp)
defer f.Close()
info, _ := f.Stat()
http.ServeContent(writer, request, name, info.ModTime(), f)
})
err := http.ListenAndServe(":8100", nil)
assert.NoError(t, err)
}
下载整个目录 #
func TestDownloadDirByGin(t *testing.T) {
dir := "./samples"
g := gin.Default()
g.Static("/samples", dir)
err := g.Run(":8100")
err = http.ListenAndServe(":8100", nil)
assert.NoError(t, err)
}
访问地址
http://127.0.0.1:8100/samples/1.mp4
自定义数据流,可用于文件加密 #
type MyStreamer struct {
File *os.File
}
func (m *MyStreamer) Read(p []byte) (n int, err error) {
n, err = m.File.Read(p)
fmt.Printf("my streamer reads %d, err = %v\n", n, err)
return n, err
}
func (m *MyStreamer) Seek(offset int64, whence int) (int64, error) {
return m.File.Seek(offset, whence)
}
func TestDownloadFileMyStreamByHttp(t *testing.T) {
fp := "./samples/1.mp4"
name := filepath.Base(fp)
http.HandleFunc("/"+name, func(writer http.ResponseWriter, request *http.Request) {
f, _ := os.Open(fp)
defer f.Close()
myStreamer := MyStreamer{File: f}
info, _ := f.Stat()
http.ServeContent(writer, request, name, info.ModTime(), &myStreamer)
})
err := http.ListenAndServe(":8100", nil)
assert.NoError(t, err)
}
控制台输出
=== RUN TestDownloadFileMyStreamByHttp
my streamer reads 512, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
my streamer reads 32768, err = <nil>
导入的代码头 #
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"net/http"
"os"
"path/filepath"
"testing"
)