当前位置: 首页 > Web前端 > HTML

golang实现http服务器提供压缩文件下载功能

时间:2023-04-02 17:19:16 HTML

最近遇到需要下载静态html报表,需要以压缩包的形式完成下载功能。实现过程中发现相关文档非常复杂,所以总结一下自己的实现。.开发环境:系统环境:MacOS+Chrome框架:beego压缩功能:tar+gzip目标压缩文件:包含数据和所有包的静态html文件首先提一下http服务器文件下载的实现,其实就是回到前端从后端发来的数据包中,设置数据头为下载文件的格式,这样当前端收到返回的response时,会直接触发下载功能(就像我们平时点击下载一样镀铬)。数据头设置格式如下:func(c*Controller)Download(){//...文件信息生成逻辑////rw为responseWriterrw:=c.Ctx.ResponseWriter//指定文件下载后的名称rw.Header().Set("Content-Disposition","attachment;filename="+"(filename)")rw.Header().Set("Content-Description","FileTransfer")//表示传输文件类型//如果是其他类型,请参考:https://www.runoob.com/http/http-content-type.htmlrw.Header().Set("Content-Type","application/octet-stream")rw.Header().Set("Content-Transfer-Encoding","binary")rw.Header().Set("Expires","0")rw.Header().Set("Cache-Control","must-revalidate")rw.Header().Set("Pragma","public")rw.WriteHeader(http.StatusOK)//文件传输是byteslice类型,在这个例子中:b是一个bytes.Buffer,你需要调用b.Bytes()http.ServeContent(rw,c.Ctx.Request,"(filename)",time.Now(),bytes.NewReader(b.Bytes()))}这样beego后台就会把header中标记为下载文件的数据包发送给前台,前台收到后会自动启动下载功能,不过这只是最后一步,如何先把我们的文件压缩一下再发给前端提供下载?如果需要下载多个文件,需要先用tar打包,再用gzip压缩,如下:nestedtarpackageThewriterofthegzippackagegw:=gzip.NewWriter(&b)tw:=tar.NewWriter(gw)dataFile:=//...文件生成逻辑,dataFile是文件类型信息,_:=dataFile.Stat()header,_:=tar.FileInfoHeader(info,"")//设置当前文件下载后的路径header.Name="report"+"/"+header.Nameerr:=tw.WriteHeader(header)iferr!=nil{utils.LogErrorln(err.Error())返回}_,err=io.Copy(tw,dataFile)iferr!=nil{utils.LogErrorln(err.Error())}//...可以继续添加文件//tarwriter和gzipwriter的关闭顺序一定不能颠倒文件文件。由于是静态html文件,我们需要将html引用的所有依赖包完整写入生成文件中的"))allStaticFiles=append(allStaticFiles,当前文件字节e)allStaticFiles=append(allStaticFiles,[]byte(""))//减下的所有静态文件staticFiles,_:=ioutil.ReadDir("static/report/")for_,tempfile:=范围staticFiles{iftempfile.Name()=="jquery.min.js"{continue}tempfilename:="static/report/"+tempfile.Name()tempfileP,_:=os.Open(tempfilename)info,_:=os.Stat(tempfilename)curFileByte:=make([]byte,info.Size())_,err:=tempfileP.Read(curFileByte)如果错误!=nil{utils.LogErrorln(err.Error())}ifisJs,_:=regexp.MatchString(`\.js$`,tempfilename);isJs{allStaticFiles=append(allStaticFiles,[]byte(""))}elseifisCss,_:=regexp.MatchString(`\.css$`,tempfilename);isCss{allStatic文件=附加(allStaticFiles,[]字节(“<样式>”))allStaticFiles=附加(allStaticFiles,curFileByte)//转换为http.File格式并返回mf:=&MyFile{Reader:bytes.NewReader(html),mif:myFileInfo{name:"report.html",data:html,},}varfhttp.File=mf返回f}好的!至此,后端文件生成->打包->压缩已经完成,我们串起来:func(c*Controller)Download(){varbbytes.Buffergw:=gzip.NewWriter(&b)tw:=tar.NewWriter(gw)//生成动态报告并添加到压缩包中//调用上面的testWrite方法dataFile:=testWrite(responseByRules,strTaskId)info,_:=dataFile.Stat()header,_:=tar.FileInfoHeader(info,"")header.Name="report_"+strTaskId+"/"+header.Nameerr:=tw.WriteHeader(header)iferr!=nil{utils.LogErrorln(err.Error())返回}_,err=io.Copy(tw,dataFile)iferr!=nil{utils.LogErrorln(err.Error())}tw.Close()gw.Close()rw:=c.Ctx.ResponseWriterrw.Header复制代码().Set("Content-Disposition","attachment;filename="+"report_"+strTaskId+".tar.gz")rw.Header().Set("Content-Description","FileTransfer")rw.Header().Set("Content-Type","application/octet-stream")rw.Header().Set("Content-Transfer-Encoding","binary")rw.Header().Set("Expires","0")rw.Header().Set("Cache-Control","must-revalidate")rw.Header().Set("Pragma","public")rw.WriteHeader(http.StatusOK)http.ServeContent(rw,c.Ctx.Request,"report_"+strTaskId+".tar.gz",time.Now(),bytes.NewReader(b.Bytes()))}后端部分已经完全实现,如何接收前端部分?在这个例子中,我做了一个按钮嵌套标签来发出请求:<按钮样式e="font-family:'SimHei';font-size:14px;font-weight:bold;color:#0d6aad;text-decoration:underline;margin-left:40px;"type="button"class="btnbtn-link">下载报告这样,在前端页面点击报告下载按钮后,会自动开始下载,并且我们后端返回的report.tar.gz文件将被下载