在没有加入下面这串代码之前,下载的压缩包一直为空。遂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")
}