位置: IT常识 - 正文

gin框架中如何实现流式下载(gin框架使用案例)

编辑:rootadmin
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 团队中之前的文件下载做得比较复杂,因为担心量太大,是后台做异步的下载,最终生成文件,传送文件到CDN服务器,最后再告诉用户下载链接。 其实在查询接口中就可以实 ...

推荐整理分享gin框架中如何实现流式下载(gin框架使用案例),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:gin框架原理详解,gin框架原理详解,gin框架教程,gin框架context,gin框架中文文档,gin框架原理详解,gin框架中文文档,gin框架原理详解,内容如对您有帮助,希望把文章链接给更多的朋友!

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!

cnblogs博客zhihuGithub公众号:一本正经的瞎扯

团队中之前的文件下载做得比较复杂,因为担心量太大,是后台做异步的下载,最终生成文件,传送文件到CDN服务器,最后再告诉用户下载链接。其实在查询接口中就可以实现流式下载,这样查询接口和下载接口可以合二为一,更加简单。

gin框架中如何实现流式下载(gin框架使用案例)

下面是我的demo:

1.建立一个download_file的文件夹作为项目文件夹go mod init download_file2.生成go.mod文件,并准备对应的包:go get github.com/gin-gonic/gin@latestgo get github.com/gin-contrib/gzip

go.mod文件内容如下:

module download_filego 1.17require github.com/gin-gonic/gin v1.8.1require (github.com/gin-contrib/gzip v0.0.6 // indirectgithub.com/gin-contrib/sse v0.1.0 // indirectgithub.com/go-playground/locales v0.14.0 // indirectgithub.com/go-playground/universal-translator v0.18.0 // indirectgithub.com/go-playground/validator/v10 v10.10.0 // indirectgithub.com/goccy/go-json v0.9.7 // indirectgithub.com/json-iterator/go v1.1.12 // indirectgithub.com/leodido/go-urn v1.2.1 // indirectgithub.com/mattn/go-isatty v0.0.14 // indirectgithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirectgithub.com/modern-go/reflect2 v1.0.2 // indirectgithub.com/pelletier/go-toml/v2 v2.0.1 // indirectgithub.com/ugorji/go/codec v1.2.7 // indirectgolang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirectgolang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirectgolang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirectgolang.org/x/text v0.3.6 // indirectgoogle.golang.org/protobuf v1.28.0 // indirectgopkg.in/yaml.v2 v2.4.0 // indirect)3.main.go文件:3.1 初始化gin框架func main() {log.SetFlags(log.LstdFlags | log.Lshortfile)engine := gin.New()// engine.Use(gzip.Gzip(gzip.DefaultCompression)) //如果需要开启gzip压缩,取消这一行的注释engine.Handle("POST", "/query", downloadFile) // 假定查询和下载接口都是这条接口实现engine.Handle("GET", "/", homepage)engine.Run(":8080")}3.2 下载链接页,模拟post到新窗口的场景func homepage(ctx *gin.Context) {ctx.Header("Content-Type", "text/html")ctx.Writer.WriteString(`<html><body>open window and to download:<a href="javascript:download()">download</a><script>function download(){ var handle = window.open("about:blank", "my_download_window");document.forms[0].target = "my_download_window";document.forms[0].json.value="ahfu test";document.forms[0].submit();}</script><form action="/query" method="POST" enctype="multipart/form-data"><input type="hidden" name="json" value=""/></form></body></html>`)}

点击链接后,弹出新窗口,在新窗口中POST json数据

3.3 流式下载功能func downloadFile(ctx *gin.Context) {reqData, has := ctx.GetPostForm("json")if !has {ctx.Data(400, "text/plain","not found json form data")return} // 此处省略查询的业务逻辑 // todo: // 下面开始下载的准备ctx.Writer.WriteHeader(200)ctx.Header("Content-Type", "text/plain; charset=utf-8")ctx.Header("Transfer-Encoding", "chunked") // 告诉浏览器,分段的流式的输出数据// ctx.Header("Content-Encoding", "gzip") // 输出不是gzip内容,又加上这个头,浏览器会拒收。这里是个实验,不要加这行代码now := time.Now()fileName := now.Format("20060102_150405.csv")ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName)) // 设置下载的文件名ctx.Writer.WriteHeaderNow()// 下面模拟一个周期非常长的数据处理和下载过程for i := 0; i < 100; i++ {ctx.Writer.WriteString("\"")ctx.Writer.WriteString(str)ctx.Writer.WriteString("\"\t")ctx.Writer.WriteString("\"")ctx.Writer.WriteString(time.Now().Format("2006-01-02 15:04:05"))ctx.Writer.WriteString("\"\n")ctx.Writer.Flush() // 产生一定的数据后, flush到浏览器端time.Sleep(time.Duration(500) * time.Millisecond)}}

打开浏览器,输入:http://127.0.0.1:8080然后点击链接,过一会儿后会出现文件下载框。点击保存后,可以看见陆续下载文件的过程。注意:为什么过了一会儿才出现文件下载框?这是由于浏览器的缓冲机制导致的。如果一开始下载的字节数很多,就会很快出现下载框

3.4 启用gzip压缩

大流量的文本下载,可能很占带宽,我们可以开启GZIP压缩:

func main() {log.SetFlags(log.LstdFlags | log.Lshortfile)engine := gin.New()engine.Use(gzip.Gzip(gzip.DefaultCompression)) //如果需要开启gzip压缩,取消这一行的注释engine.Handle("POST", "/query", downloadFile) // 假定查询和下载接口都是这条接口实现engine.Handle("GET", "/", homepage)engine.Run(":8080")}

gin框架中已经提供gzip压缩的能力。

3.5 完整代码:// main.gopackage mainimport ("fmt""log""time""github.com/gin-contrib/gzip""github.com/gin-gonic/gin")func useGzip(engine *gin.Engine) {engine.Use(gzip.Gzip(gzip.DefaultCompression))}func main() {log.SetFlags(log.LstdFlags | log.Lshortfile)engine := gin.New()// engine.Use(gzip.Gzip(gzip.DefaultCompression)) //如果需要开启gzip压缩,取消这一行的注释engine.Handle("POST", "/query", downloadFile)engine.Handle("GET", "/", homepage)engine.Run(":8080")}func downloadFile(ctx *gin.Context) {reqData, has := ctx.GetPostForm("json")if !has {ctx.Data(400, "text/plain","not found json form data")return} // 此处省略查询的业务逻辑 // todo: // 下面开始下载的准备ctx.Writer.WriteHeader(200)ctx.Header("Content-Type", "text/plain; charset=utf-8")ctx.Header("Transfer-Encoding", "chunked") // 告诉浏览器,分段的流式的输出数据// ctx.Header("Content-Encoding", "gzip") // 输出不是gzip内容,又加上这个头,浏览器会拒收。这里是个实验,不要加这行代码now := time.Now()fileName := now.Format("20060102_150405.csv")ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName)) // 设置下载的文件名ctx.Writer.WriteHeaderNow()// 下面模拟一个周期非常长的数据处理和下载过程for i := 0; i < 100; i++ {ctx.Writer.WriteString("\"")ctx.Writer.WriteString(str)ctx.Writer.WriteString("\"\t")ctx.Writer.WriteString("\"")ctx.Writer.WriteString(time.Now().Format("2006-01-02 15:04:05"))ctx.Writer.WriteString("\"\n")ctx.Writer.Flush() // 产生一定的数据后, flush到浏览器端time.Sleep(time.Duration(500) * time.Millisecond)}}func homepage(ctx *gin.Context) {ctx.Header("Content-Type", "text/html")ctx.Writer.WriteString(`<html><body>open window and to download:<a href="javascript:download()">download</a><script>function download(){ var handle = window.open("about:blank", "my_download_window");document.forms[0].target = "my_download_window";document.forms[0].json.value="ahfu test";document.forms[0].submit();}</script><form action="/query" method="POST" enctype="multipart/form-data"><input type="hidden" name="json" value=""/></form></body></html>`)}

have fun. ?

本文链接地址:https://www.jiuchutong.com/zhishi/313079.html 转载请保留说明!

上一篇:Nginx 防盗链(nginx防盗链的作用)

下一篇:python多线程和多进程之间的联系(python多线程多核)

  • 营销的几个核心价值,如何利用微信做企业营销(营销的几个核心是什么)

    营销的几个核心价值,如何利用微信做企业营销(营销的几个核心是什么)

  • oppok9pro怎么投屏(oppok9手机怎么投屏)

    oppok9pro怎么投屏(oppok9手机怎么投屏)

  • 怎么查ip地址(怎么查ip地址冲突)

    怎么查ip地址(怎么查ip地址冲突)

  • 拼多多老是发信息过来怎么取消啊(拼多多老是发信息怎么办)

    拼多多老是发信息过来怎么取消啊(拼多多老是发信息怎么办)

  • 淘宝收藏夹上限(淘宝收藏夹上限提升到4000)

    淘宝收藏夹上限(淘宝收藏夹上限提升到4000)

  • 苹果手表5代微信发不出去(苹果手表5微信怎么用)

    苹果手表5代微信发不出去(苹果手表5微信怎么用)

  • 手机一下充电一下不充电怎么回事(手机一下充电一下又不充电)

    手机一下充电一下不充电怎么回事(手机一下充电一下又不充电)

  • 华为手机悬浮球怎么开(华为手机悬浮球在哪里打开)

    华为手机悬浮球怎么开(华为手机悬浮球在哪里打开)

  • 蓝牙key是什么(手机银行蓝牙key配对不上)

    蓝牙key是什么(手机银行蓝牙key配对不上)

  • 投屏需要流量吗(投屏费不费流量)

    投屏需要流量吗(投屏费不费流量)

  • 手机左上角显示HD是开启什么功能(手机左上角显示时间怎么关闭)

    手机左上角显示HD是开启什么功能(手机左上角显示时间怎么关闭)

  • 京东申请退款要确认收货吗(京东申请退款要多久才能审核成功)

    京东申请退款要确认收货吗(京东申请退款要多久才能审核成功)

  • 电脑的ip地址怎么查(电脑的ip地址怎么设置才正确)

    电脑的ip地址怎么查(电脑的ip地址怎么设置才正确)

  • ios13查找别人id(ios13查找我的iphone怎么查找别人的手机)

    ios13查找别人id(ios13查找我的iphone怎么查找别人的手机)

  • excel递减排序在哪(excel表递减排序)

    excel递减排序在哪(excel表递减排序)

  • 魅族16th怎么进入开发者(魅族16如何)

    魅族16th怎么进入开发者(魅族16如何)

  • iphone11怎么拍夜景(如何用iphone11拍夜景)

    iphone11怎么拍夜景(如何用iphone11拍夜景)

  • 中秋活动的意义(中秋活动目的内容)

    中秋活动的意义(中秋活动目的内容)

  • 快手mcn入驻条件(快手加入mcn有什么坏处)

    快手mcn入驻条件(快手加入mcn有什么坏处)

  • 名创优品如何加盟(名创优品怎么加会员)

    名创优品如何加盟(名创优品怎么加会员)

  • 抖音怎么录屏幕视频(怎么拍抖音视频)

    抖音怎么录屏幕视频(怎么拍抖音视频)

  • 小米e55a和e55c区别(小米e55a和e55x)

    小米e55a和e55c区别(小米e55a和e55x)

  • qq号可以改吗(qq号可以改吗?纯数字的)

    qq号可以改吗(qq号可以改吗?纯数字的)

  • vue怎么调时间(vue 当前时间)

    vue怎么调时间(vue 当前时间)

  • 打电话关机是怎么回事(打电话关机怎么找到位置)

    打电话关机是怎么回事(打电话关机怎么找到位置)

  • 汇算清缴后发现多结转了成本
  • 签订合同后付款
  • 国外公司税号查询
  • 购进电脑怎么折旧
  • 想要自己开厂应该怎么做
  • 小企业以前年度损益调整科目编码
  • 外企缴纳社保
  • 机场工作人员的家属票
  • 免税产品的销项税
  • 冲销去年暂估费用
  • 发票作为付款凭证的案例
  • 税务局查账一般需要几天
  • 金税盘要钱不
  • 增值税开票系统收款人在哪里设置
  • 公司租房可以入公积金吗
  • 子公司销售给母公司商品
  • 小规模印花税怎么报
  • 成本费用利润率越高,说明企业盈利能力
  • mac与iphone联动
  • 事业单位个税手续费返还需要上缴财政吗
  • win7防火墙设置不了
  • 预存500抵扣1000是几折活动?
  • 防水工程质量问题
  • 银行多收的开户费怎么办
  • win11系统咋样
  • 年底会计结账
  • 个体工商户税收标准2023年
  • 固定资产折旧怎么做账务处理
  • 现金折扣发生销售退回
  • 收到政府的补助交所得税么
  • psd格式文档
  • 离职赔偿金计入什么费用
  • php框架yii
  • rest for api
  • web前端基础教程
  • 季度做账是什么意思
  • 小规模申报增值税减免税申报明细表
  • 企业增值税发票税率是多少
  • 开办费计入哪个会计科目
  • 公司垫付的工伤医药费怎么报销
  • 企业所得税的成本
  • 成本法的处置
  • 公司亏损注销了怎么赔偿
  • 不征税收入与免税收入有哪些
  • 企业取得财产转让收入
  • 年终奖个税计税方式
  • 当月只有进项票没有销项票怎么办
  • 公司购买黄金送客户可以抵税吗
  • 什么叫做进项税不得抵扣
  • 全额工资和实发工资
  • 资产负债表所有者权益和利润表关系
  • 生产成本和主营业务收入的关系
  • cf游戏初始化失败是因为什么
  • ubuntu怎样
  • freebsd与linux
  • 进程中svchost
  • ias.exe是什么程序
  • 重装win7系统后桌面没东西
  • win8使用技巧 图文
  • 系统运行缓慢解决方法
  • WIN7系统安装
  • win1020h2正式版
  • linux系统怎么访问网页
  • linux如何查看用户的信息
  • windows 10预览版
  • android获取音频信息
  • Android中SQLite数据库的使用
  • unity mobile3d
  • mailto的使用技巧分享
  • 浅谈幼儿良好行为的培养论文
  • javascript中cookie
  • ubuntu修改默认桌面环境
  • 如何用python开发软件
  • 获取手机信息的渠道
  • 税盘上怎么查每个月一共开了多少金额
  • 山东中信银行电话
  • 政府征用土地社保补偿标准
  • 差额开票扣除额多补税
  • 90平房子税
  • 税收筹划六种方法
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设