golang微服務(wù)框架go-zero系列-4:go-zero文件服務(wù)

golang微服務(wù)框架go-zero系列-4:go-zero文件服務(wù)

go-zero本身支持文件服務(wù),但是我們需要寫相關(guān)的handler文件,本文目的在于

  • 不寫任何一個和文件相關(guān)的handler
  • 如果有新的文件,直接把文件模板到某個特定目錄就好,不要動任何go代碼

需求在這里,開擼吧

在代碼開始前,你可能需要閱讀

golang微服務(wù)框架go-zero系列-1:在go-zero中使用XormV2
golang微服務(wù)框架go-zero系列-2:在go-zero中使用jwt-token鑒權(quán)實踐
golang微服務(wù)框架go-zero系列-3:擴展go-zero,使之支持html模板解析自動化

注意

微服務(wù)講究資源分離,實際生產(chǎn)過程中盡量使用專業(yè)的文件服務(wù)器或者OSS等第三方存儲平臺

file服務(wù)實現(xiàn)思路

gin中有專門的static file服務(wù)封裝,go-zero目前并沒有提供。目前go-zero提供非常嚴格的路徑匹配,如
訪問
/asset/l1.jpg 將映射到 /asset/:1對應(yīng)的handlerlv1
/asset/l1/l2.jpg 將映射到 /asset/:1/:2對應(yīng)的handlerlv2
這有如下倆種情況

映射指定路徑到單個文件

比如我們需要訪問favourite.ico,系統(tǒng)指向./www/favourite.ico文件,代碼如下

//處理函數(shù),傳入文件地址
func filehandler(filepath string) http.HandlerFunc {
    return func(w http.ResponseWriter, req *http.Request) {
        http.ServeFile(w, req, filepath)
    }
}

在router里面直接調(diào)用AddRoute方法添加單個路由

func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {

//這里直接添加單個
engine.AddRoute(
                rest.Route{
                    Method:  http.MethodGet,
                    Path:    "/favourite.ico",
                    Handler: filehandler("./www/favourite.ico"),
                })
}

映射指定目錄并提供服務(wù)

實際過程中我們需要對外暴露某一個目錄,比如/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                             

如果使用單個文件的方式來實現(xiàn),肯定不合理,因為router會非常大,怎么解決這個問題?我們可以使用如下方法實現(xiàn)文件夾服務(wù)

//
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)

    }
}

如上函數(shù)的核心是http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))函數(shù),這個函數(shù)的核心功能是將映patern格式映射到某一個目錄filedir

  • patern:請求路徑格式/assets/:1,/assets/:1/:2這種
  • filedir:映射對應(yīng)的文件夾./assets/這種

那么我們只需要構(gòu)建多級文件訪問格式和dirhandler的映射關(guān)系即可

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函數(shù)中配置

rt := router.NewPatRouter()
    rt.SetNotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        //這里內(nèi)容可以定制
        w.Write([]byte("服務(wù)器開小差了,這里可定制"))
    }))
    server := rest.MustNewServer(c.RestConf, rest.WithRouter(rt))

此時請求http://127.0.0.1:8888/hello,系統(tǒng)響應(yīng)
服務(wù)器開小差了,這里可定制

測試

啟動系統(tǒng)后運行

E:\workspace@go\gozero\file>go run file.go
2020/09/05 20:18:24 {"@timestamp":"2020-09-05T20: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-05T20:18:24.682+08","level":"info","content":"register dir  /asset/:1  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir  /asset/:1/:2  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir  /asset/:1/:2/:3  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir  /asset/:1/:2/:3/:4  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.697+08","level":"info","content":"register dir  /asset/:1/:2/:3/:4/:5  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.697+08","level":"info","content":"register dir  /asset/:1/:2/:3/:4/:5/:6  ./assets"}
{"@timestamp":"2020-09-05T20:18:24.698+08","level":"info","content":"register dir  /asset/:1/:2/:3/:4/:5/:6/:7  ./assets"}

訪問系統(tǒng)都能正常響應(yīng)

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中根據(jù)req.URL.path來實現(xiàn)文件服務(wù),如何實現(xiàn)呢?

下章預(yù)告

單體應(yīng)用需要的基本梳理完,明天開始微服務(wù)

本文代碼獲取

關(guān)注公眾號betaidea 輸入file即可獲得本文相關(guān)代碼
關(guān)注公眾號betaidea 輸入html即可獲得html解析相關(guān)代碼
關(guān)注公眾號betaidea 輸入jwt即可獲得gozero集成jwt-token相關(guān)代碼
關(guān)注公眾號betaidea 輸入gozero即可gozero入門代碼

廣而告之

送福利了uniapp用戶福音來啦!
歷經(jīng)數(shù)十萬用戶考驗,我們的客服系統(tǒng)終于對外提供服務(wù)了。
你還在為商城接入客服煩惱嗎?只需一行代碼,即可接入啦!!
只需一行代碼!!!!

/*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
            }
        }
    }   

效果杠杠的


客服效果

開發(fā)文檔地址
http://kefu.techidea8.com/html/wiki/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容