Go语言中如何修改响应体文件压缩后的Header(含日期)
解决方案
核心问题原因
你使用archive.Create()方法时,zip包会默认采用零时间戳(对应Unix时间0),在部分时区下会显示为1979年11月30日。要修改这个时间,需要手动为每个zip内的文件设置时间戳——无需修改响应体的Header,因为io.ReadCloser类型的响应体本身不包含文件元数据(比如修改时间),这些数据要么从GET请求的响应头提取,要么直接指定当前时间。
可行方案
方案1:直接设置为当前时间
用zip.Writer.CreateHeader()替代Create(),手动构造zip.FileHeader并指定修改时间:
修改后的代码示例:
archive := zip.NewWriter(w) attachment := "attachment; filename=someZipFile.zip" c.Writer.Header().Set("Content-Disposition", attachment) currentTime := time.Now() // 获取当前时间 for i := 0; i < len(bodies); i++ { defer bodies[i].Close() filePath := "someZipFile/" + filenames[i] // 构造自定义文件头 fileHeader := &zip.FileHeader{ Name: filePath, Modified: currentTime, } // 设置文件权限(可选,默认0644对应普通文件读写权限) fileHeader.SetMode(0644) w, err := archive.CreateHeader(fileHeader) if err != nil { fmt.Println("File couldn't be created:", err) return true } if _, err := io.Copy(w, bodies[i]); err != nil { fmt.Println("File couldn't be written:", err) return true } } if err := archive.Close(); err != nil { fmt.Println("Failed to close zip writer:", err) return true }
方案2:从GET响应头提取原文件修改时间
如果你的每个GET请求响应头包含Last-Modified字段(多数静态文件服务器会返回),需要在获取响应时保存完整的http.Response对象(而非仅Body),再解析该字段设置到zip文件头:
- 先调整保存响应的逻辑,比如将
bodies替换为responses []*http.Response:
// 示例:发起GET请求并保存完整响应 responses := make([]*http.Response, 0) for _, url := range downloadUrls { resp, err := http.Get(url) if err != nil { // 处理请求错误 return true } responses = append(responses, resp) }
- 压缩时解析
Last-Modified字段:
archive := zip.NewWriter(w) attachment := "attachment; filename=someZipFile.zip" c.Writer.Header().Set("Content-Disposition", attachment) for i := 0; i < len(responses); i++ { resp := responses[i] defer resp.Body.Close() filePath := "someZipFile/" + filenames[i] // 初始化文件头,默认用当前时间 fileHeader := &zip.FileHeader{ Name: filePath, Modified: time.Now(), } fileHeader.SetMode(0644) // 尝试从响应头提取并解析Last-Modified if lastModifiedStr := resp.Header.Get("Last-Modified"); lastModifiedStr != "" { lastModified, err := http.ParseTime(lastModifiedStr) if err == nil { fileHeader.Modified = lastModified } else { fmt.Println("Failed to parse Last-Modified:", err) } } w, err := archive.CreateHeader(fileHeader) if err != nil { fmt.Println("File couldn't be created:", err) return true } if _, err := io.Copy(w, resp.Body); err != nil { fmt.Println("File couldn't be written:", err) return true } } if err := archive.Close(); err != nil { fmt.Println("Failed to close zip writer:", err) return true }
关键说明
io.ReadCloser仅负责文件内容读取,不包含文件元数据,无需修改它的Header。CreateHeader()是核心:它允许你完全控制zip内文件的元数据,包括修改时间、权限等。- 权限设置
SetMode()是可选操作,可根据需求调整文件的读写权限。
内容的提问来源于stack exchange,提问作者ppg87
相关产品推荐
相关产品推荐

