限速下载
php版本:
<?php // 将发送到客户端的本地文件 $local_file='abc.zip'; // 文件名 $download_file='your-download-name.zip'; // 设置下载速率(=> 31.2 kb/s) $download_rate=31.2; if(file_exists($local_file)&&is_file($local_file)){ header('Cache-control: private');// 发送 headers header('Content-Type: application/octet-stream'); header('Content-Length: '.filesize($local_file)); header('Content-Disposition: filename='.$download_file); flush();// 刷新内容 $file=fopen($local_file,"r"); while (!feof($file)){ print fread($file,round($download_rate*1024));// 发送当前部分文件给浏览者 flush();// flush 内容输出到浏览器端 sleep(1);// 终端1秒后继续 } fclose($file);// 关闭文件流 }else{ die('Error: 文件 '.$local_file.' 不存在!'); }
go版本:
package main import ( "bufio" //"bufio" //"bytes" "context" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/juju/ratelimit" "io" //"io" "log" "net/http" "syscall" "time" "os/signal" //"github.com/juju/ratelimit" "os" "path/filepath" ) type Web struct { cache_path string } func (w *Web) create_cache() { w.cache_path = filepath.Join("./", "file_server_cache") if _, err := os.Stat(w.cache_path); err != nil { // not exists if err := os.MkdirAll(w.cache_path, os.ModePerm); err != nil { log.Fatal(err) } } } func (w *Web) index(c *gin.Context) { //all_file, _ := get_all_file(w.cache_path) //fmt.Println(all_file) //c.JSON(200, gin.H{ // "message": "pong", //}) } func (w *Web) download_handler(c *gin.Context) { download_file := c.Query("file_name") file_path := "./file_server_cache/" + download_file if _, err := os.Stat(file_path); err != nil { c.JSON(200, gin.H{ "code": "1", "msg":"error, download_file not exists", }) return } c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", download_file)) c.Writer.Header().Add("Content-Type", "application/octet-stream") //c.File("./file_server_cache/"+download_file) file, _ := os.Open(file_path) // new 一个速度限制器,每秒传输 100 Kb(第一个值 是下载速度,第二个是会影响下载速度,建议两个一样) bucket := ratelimit.NewBucketWithRate(100 * 1024,100 * 1024) reader:= bufio.NewReader(file) io.Copy(c.Writer,ratelimit.Reader(reader,bucket)) } func get_all_file(dir string) ([][]string, error) { dirs, err := os.ReadDir(dir) if err != nil { return nil, err } var all_file [][]string for _, v := range dirs { if !v.IsDir() { single_file := []string{v.Name(), filepath.Join(dir, v.Name())} all_file = append(all_file, single_file) } } return all_file, nil } //参考地址:https://www.cnblogs.com/gopher-zero/p/14754526.html func main() { w := Web{} w.create_cache() router := gin.Default() router.GET("/", w.index) router.GET("/download", w.download_handler) srv := &http.Server{ Addr: ":8080", Handler: router, } go func() { err := srv.ListenAndServe() if err!=nil&&errors.Is(err,http.ErrServerClosed){ log.Printf("listen:%s\n",err) } }() quit := make(chan os.Signal) signal.Notify(quit,syscall.SIGINT,syscall.SIGTERM) <-quit log.Println("Shutting down server..") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() err := srv.Shutdown(ctx) if err!=nil{ log.Fatal("Server forced to shutdown:", err) } log.Println("Server exiting") }