golang - 下载大文件,实时返回前端下载进度,实现下载进度条

示例:

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path"

	//"github.com/kataras/iris"
	"github.com/kataras/iris/v12"
	"time"
)

func doSomething() {
	time.Sleep(time.Second * 10)
	fmt.Println("sleep end ------")
}

// DownloadFile 下载指定 URL 的文件并保存到指定路径
//func DownloadFile(url string, filePath string) error {
//	// 发起 GET 请求获取文件
//	resp, err := http.Get(url)
//	if err != nil {
//		return err
//	}
//	defer resp.Body.Close()
//
//	// 创建本地文件
//	out, err := os.Create(filePath)
//	if err != nil {
//		return err
//	}
//	defer out.Close()
//
//	// 将响应的内容写入本地文件
//	_, err = io.Copy(out, resp.Body)
//	if err != nil {
//		return err
//	}
//
//	return nil
//}

func DownloadFile(ctx iris.Context, url string, filePath string) error {

	// 获取 http.ResponseWriter
	w := ctx.ResponseWriter()

	// 发起 GET 请求获取文件
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// 创建本地文件
	out, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer out.Close()

	 将响应的内容写入本地文件
	//_, err = io.Copy(out, resp.Body)
	//if err != nil {
	//	return err
	//}

	writer := &ProgressWriter{
		Total:    resp.ContentLength,
		Response: w,
	}
	_, err = io.Copy(out, io.TeeReader(resp.Body, writer))
	if err != nil {
		fmt.Println("File write failed:", err)
		http.Error(w, "File write failed", http.StatusInternalServerError)
	}

	w.Write([]byte("File download completed"))

	return nil
}

type ProgressWriter struct {
	Total       int64
	Downloaded  int64
	CurrentStep int
	Response    http.ResponseWriter
}

func (pw *ProgressWriter) Write(p []byte) (int, error) {
	n := len(p)
	pw.Downloaded += int64(n)

	// 返回百分比
	//progress := float64(pw.Downloaded) / float64(pw.Total) * 100.0
	//
	//if int(progress) > pw.CurrentStep {
	//	pw.CurrentStep = int(progress)
	//	pw.Response.Write([]byte(fmt.Sprintf("Downloading: %.2f%%\n", progress)))
	//	pw.Response.(http.Flusher).Flush()
	//}

	progress := pw.Downloaded

	if int(progress) > pw.CurrentStep {
		pw.CurrentStep = int(progress)
		pw.Response.Write([]byte(fmt.Sprintf("%d/%d\n", progress, pw.Total)))
		pw.Response.(http.Flusher).Flush()
	}

	return n, nil
}

func main() {
	app := iris.New()

	// 定义路由和处理函数
	app.Get("/", func(ctx iris.Context) {
		go doSomething()
		ctx.HTML("

Welcome to Iris

") }) app.Get("/hello", func(ctx iris.Context) { start := time.Now() currPath, _ := os.Getwd() name := ctx.URLParam("name") UpgradePKGPath := path.Join(currPath, "file.bot") fmt.Println("UpgradePKGPath: ", UpgradePKGPath) DownloadUrl := "https://tests%3D" err := DownloadFile(ctx, DownloadUrl, UpgradePKGPath) if err != nil { fmt.Println("Error:", err) } duration := time.Since(start) fmt.Println("执行时间:", duration) ctx.Writef("Hello, %s!", name) }) // 启动应用程序 app.Run(iris.Addr(":8080")) }

效果:

golang - 下载大文件,实时返回前端下载进度,实现下载进度条_第1张图片

 

你可能感兴趣的:(Golang,iphone,ios,Golang)