分享
  1. 首页
  2. 文章

golang微服务框架go-zero系列-4:go-zero文件服务

非正式解决方案 · · 1598 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang微服务框架go-zero系列-4:go-zero文件服务

go-zero本身支持文件服务,但是我们需要写相关的handler文件,本文目的在于

  • 不写任何一个和文件相关的handler
  • 如果有新的文件,直接把文件模板到某个特定目录就好,不要动任何go代码

需求在这里,开撸吧

在代码开始前,你可能需要阅读

golang微服务框架go-zero系列-1:在go-zero中使用XormV2
golang微服务框架go-zero系列-2:在go-zero中使用jwt-token鉴权实践
golang微服务框架go-zero系列-3:扩展go-zero,使之支持html模板解析自动化

注意

微服务讲究资源分离,实际生产过程中尽量使用专业的文件服务器或者OSS等第三方存储平台

file服务实现思路

gin中有专门的static file服务封装,go-zero目前并没有提供。目前go-zero提供非常严格的路径匹配,如
访问
/asset/l1.jpg 将映射到 /asset/:1对应的handlerlv1
/asset/l1/l2.jpg 将映射到 /asset/:1/:2对应的handlerlv2
这有如下俩种情况

映射指定路径到单个文件

比如我们需要访问favourite.ico,系统指向./www/favourite.ico文件,代码如下

//处理函数,传入文件地址
func filehandler(filepath string) http.HandlerFunc {
 return func(w http.ResponseWriter, req *http.Request) {
 http.ServeFile(w, req, filepath)
 }
}

在router里面直接调用AddRoute方法添加单个路由

func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
//这里直接添加单个
engine.AddRoute(
 rest.Route{
 Method: http.MethodGet,
 Path: "/favourite.ico",
 Handler: filehandler("./www/favourite.ico"),
 })
}

映射指定目录并提供服务

实际过程中我们需要对外暴露某一个目录,比如/assets/目录,该目录下存放一些资源文件如css,js,img

tree /f
+---assets 
| +---css 
| +---fonts 
| +---images 
| +---js 
| \---plugins 
| +---font-awesome 
| | +---css 
| | \---fonts 
| +---fontawesome 
| | +---css 
| | \---fonts 
| +---ionicons 
| | +---css 
| | \---fonts 
| +---jquery.contextmenu 
| | \---images 
| +---jquery.pin 
| | +---css 
| | \---images 
| +---jqueryui-1.12.1 
| | +---external 
| | | \---jquery 
| | \---images 
| \---swiper-4.5.3 
| +---css 
| \---js 

如果使用单个文件的方式来实现,肯定不合理,因为router会非常大,怎么解决这个问题?我们可以使用如下方法实现文件夹服务

//
func dirhandler(patern, filedir string) http.HandlerFunc {
 return func(w http.ResponseWriter, req *http.Request) {
 handler := http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))
 handler.ServeHTTP(w, req)
 }
}

如上函数的核心是http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))函数,这个函数的核心功能是将映patern格式映射到某一个目录filedir

  • patern:请求路径格式/assets/:1,/assets/:1/:2这种
  • filedir:映射对应的文件夹./assets/这种

那么我们只需要构建多级文件访问格式和dirhandler的映射关系即可

func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
 //这里注册
 dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"}
 patern := "/asset/"
 dirpath := "./assets/"
 for i := 1; i < len(dirlevel); i++ {
 path := prefix + strings.Join(dirlevel[:i], "/")
 //最后生成 /asset
 engine.AddRoute(
 rest.Route{
 Method: http.MethodGet,
 Path: path,
 Handler: dirhandler(patern,dirpath),
 })
 logx.Infof("register dir %s %s", path,dirpath)
 }
}

404

404可以在main函数中配置

rt := router.NewPatRouter()
 rt.SetNotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 //这里内容可以定制
 w.Write([]byte("服务器开小差了,这里可定制"))
 }))
 server := rest.MustNewServer(c.RestConf, rest.WithRouter(rt))

此时请求http://127.0.0.1:8888/hello,系统响应
服务器开小差了,这里可定制

测试

启动系统后运行

E:\workspace@go\gozero\file>go run file.go
2020年09月05日 20:18:24 {"@timestamp":"2020年09月05日T20:18:24.682+08","level":"info","content":"{{{file-api { console logs info false 0 100} pro { 0 }} 0.0.0.0 8081 false 10000 1048576 3000 900 {false 0s []}} [/asset/=./assets]}"} 
{"@timestamp":"2020年09月05日T20:18:24.682+08","level":"info","content":"register dir /asset/:1 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2/:3 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2/:3/:4 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.697+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.697+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5/:6 ./assets"}
{"@timestamp":"2020年09月05日T20:18:24.698+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5/:6/:7 ./assets"}

访问系统都能正常响应

http://127.0.0.1:8888/asset/images/avatar.jpg
http://127.0.0.1:8888/asset/js/test.js
http://127.0.0.1:8888/asset/js/lv2/test.js

注意,请求的是/asset/** 不是/assets/**

思考一下

我们可以在NotFoundHandler中根据req.URL.path来实现文件服务,如何实现呢?

下章预告

单体应用需要的基本梳理完,明天开始微服务

本文代码获取

关注公众号betaidea 输入file即可获得本文相关代码
关注公众号betaidea 输入html即可获得html解析相关代码
关注公众号betaidea 输入jwt即可获得gozero集成jwt-token相关代码
关注公众号betaidea 输入gozero即可gozero入门代码

广而告之

送福利了uniapp用户福音来啦!
历经数十万用户考验,我们的客服系统终于对外提供服务了。
你还在为商城接入客服烦恼吗?只需一行代码,即可接入啦!!
只需一行代码!!!!

/*kefu.vue*/
<template>
 <view>
 <IdeaKefu :siteid="siteId" ></IdeaKefu>
 </view>
</template>
<script>
 import IdeaKefu from "@/components/idea-kefu/idea-kefu.vue"
 export default {
 components:{
 IdeaKefu
 },
 data() {
 return {
 siteId:2
 }
 }
 } 

效果杠杠的


客服效果

开发文档地址
http://kefu.techidea8.com/html/wiki/


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:非正式解决方案

查看原文:golang微服务框架go-zero系列-4:go-zero文件服务

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1598 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏