【Go】gin框架生成压缩包与下载文件

在没有加入下面这串代码之前,下载的压缩包一直为空。遂debug了两个小时。。。
可以在服务端本地创建压缩包。单独将服务端本地的压缩包发送给客户端也是没问题的。但是两个合起来,客户端接收到的压缩包内容就为空了。
期间也尝试了
zipFile.Close()
zipWriter.Close()
但是zipFile不能立刻关

	// 关闭 ZIP 归档,确保所有数据都被写入压缩包文件
	err = zipWriter.Close()
	if err != nil {
		fmt.Println("无法关闭 ZIP 归档:", err)
		return
	}

将缓冲区中的数据刷新到磁盘上的压缩包文件。
在创建 ZIP 归档后,需要调用 zipWriter.Close() 来确保所有的数据都被写入压缩包文件。在 zipWriter.Close() 被调用之前,压缩包文件可能仍然处于打开状态,并且尚未完全写入磁盘。

func download(c *gin.Context) {
	tmpData := make(map[string]interface{})
	if err := c.ShouldBindJSON(&tmpData); err != nil {
		log.Println(err)
		c.JSON(http.StatusBadRequest, gin.H{"msg": "请求参数错误"})
		return
	}
	// 获取要下载的文件列表
	filePaths := tmpData["selectedIds"].([]interface{})
	// 获取当前时间
	currentTime := time.Now()
	// 格式化为特定格式
	formattedTime := currentTime.Format("2006-01-02-15-04")
	zipFilename := formattedTime + ".zip"
	tempZipPath := filepath.Join(zipFilename)
	// 创建压缩包文件
	zipFile, err := os.Create(tempZipPath)
	if err != nil {
		fmt.Println("无法创建压缩包文件:", err)
		return
	}
	defer zipFile.Close()

	// 创建 ZIP 归档
	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	for _, filePath := range filePaths {
		idStr := fmt.Sprintf("%v", filePath)
		filePath := filepath.Join("nuclei-templates-original", idStr+".yaml")
		fmt.Printf(filePath)

		// 添加文件到 ZIP 归档
		err = addFileToZip(zipWriter, filePath)
		if err != nil {
			fmt.Println("无法添加文件到压缩包:", err)
			return
		}

		fmt.Println("文件已成功添加到压缩包中。")
	}

	// 关闭 ZIP 归档,确保所有数据都被写入压缩包文件
	err = zipWriter.Close()
	if err != nil {
		fmt.Println("无法关闭 ZIP 归档:", err)
		return
	}

	file, err := os.Open(tempZipPath)
	if err != nil {
		c.String(http.StatusInternalServerError, "无法打开压缩包")
		return
	}

	// 获取文件信息
	fileInfo, err := file.Stat()
	if err != nil {
		c.String(http.StatusInternalServerError, "无法获取压缩包信息")
		return
	}

	// 设置响应头
	c.Header("Content-Type", "application/zip")
	c.Header("Content-Disposition", "attachment; filename="+tempZipPath)
	c.Header("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))

	// 将压缩包内容发送给客户端
	_, err = io.Copy(c.Writer, file)
	if err != nil {
		c.String(http.StatusInternalServerError, "无法发送压缩包")
		return
	}

}

func addFileToZip(zipWriter *zip.Writer, filePath string) error {
	// 打开要添加的文件
	file, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 获取文件信息
	info, err := file.Stat()
	if err != nil {
		return err
	}

	// 创建 ZIP 归档中的文件
	header, err := zip.FileInfoHeader(info)
	if err != nil {
		return err
	}

	// 设置 ZIP 归档中的文件名
	header.Name = filepath.Base(filePath)

	// 写入文件到 ZIP 归档
	writer, err := zipWriter.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, file)
	return err
}

gin框架跟着 狂神说,一个小时速成,讲的很好
这是老师课上的源码

package main
import (
    "encoding/json"
    "log"
    "net/http"
    "github.com/gin-gonic/gin"
    "github.com/thinkerou/favicon"
)
//自定义go中间件即拦截器
//给所有请求使用  则不不写在下列方法里,写了则拦截指定方法的请求

func myHandler() (gin.HandlerFunc) {
    //通过自定义的中间件,设置的值,在后续处理只要调用了这个中间件的都可以拿到这里的参数
    return func(context *gin.Context) {
        context.Set("usersession","userid-1")
        //if ...
        context.Next() //放行
        context.Abort() //阻止
    }
}
func main() {
    //创建一个服务
    ginServer := gin.Default()
    ginServer.Use(favicon.New("./favicon.ico"))
    //加载静态页面
    ginServer.LoadHTMLGlob("templates/*")
    //加载资源目录
    ginServer.Static("/static","./static")
    //Gin Restful
    ginServer.GET("/hello",myHandler(),func(Context *gin.Context) {
        //取出中间件中的值
        usersession := Context.MustGet("userSession").(string) //空接口转换为string
        log.Println("------->",usersession)
        Context.JSON(200,gin.H{"msg":"hello,world"})
    })
    ginServer.POST("/user",func(c *gin.Context) {
        c.JSON(200,gin.H{"msg":"post,user"})
    })
    ginServer.PUT("/user")
    ginServer.DELETE("/user")
    //响应一个页面给前端
    ginServer.GET("/index",func(Context *gin.Context) {
        Context.HTML(http.StatusOK,"index.html",gin.H{
            "msg":"这是go后台传递来的数据",
        })      
    //接收前端传递过来的参数
    //info?userid=xxx&username=kuangshen
    // ginServer.GET("/user/info",func(context *gin.Context) {
    //  userid := context.Query("userid")
    //  username := context.Query("username")
    //  context.JSON(http.StatusOK,gin.H{
    //      "userid": userid,
    //      "username": username,
    //  })  
    // })
    //info/1/kaungshen
    ginServer.GET("/user/info/:userid/:username",func(context *gin.Context) {
        userid := context.Param("userid")
        username := context.Param("username")
        context.JSON(200,gin.H{
            "userid": userid,
            "username": username,
        })
    })
    //掌握技术后面的应用- 掌握基础知识,加以了解web知识
    // 前端给后端传递 json
    ginServer.POST("/json",func(context *gin.Context) {
        //request.body
        //[]body 返回的是切片
        data,_ := context.GetRawData()
        var m map[string]interface{}
        //包装为json数据 []byte
        _ = json.Unmarshal(data,&m)
        context.JSON(200,m)
    })
    //支持表单
    ginServer.POST("/user/add",func(context *gin.Context) {
        username := context.PostForm("username")
        password := context.PostForm("password")
        context.JSON(200,gin.H{
            "msg":"ok",
            "username":username,
            "password":password,
        })
    })
    //路由
    ginServer.GET("/test",func(context *gin.Context) {
        //重定向
        context.Redirect(301,"http://baidu.com")        
    })
    //404 NoRoute
    ginServer.NoRoute(func(context *gin.Context) {
        context.HTML(http.StatusNotFound,"404.html",nil)
    })
    //路由组
    userGroup := ginServer.Group("/user")
    {
        userGroup.GET("/add")
        userGroup.POST("/login")
        userGroup.POST("/logout")
    }
    orderGroup := ginServer.Group("order")
    {
        orderGroup.GET("/add")
        orderGroup.DELETE("/delete")
    }  
})
    //服务器端口
    ginServer.Run(":8082")
}

你可能感兴趣的:(golang,gin,开发语言)