05 . Go+Vue開發一個線上外賣應用(Session集成及修改用戶頭像到Fastdfs)
用戶頭像上傳
功能介紹
在用戶中心中,允許用戶更換自己的頭像。因此,我們開發上傳一張圖片到伺服器,並保存成為用戶的頭像。
介面解析
在用戶模組的控制器MemberController中,解析頭像上傳的介面,解析如下:
func (mc *MemberController) Router(engine *gin.Engine) {
...
//用戶頭像上傳
engine.POST("/api/upload/avator",mc.uploadAvator)
}
在文件上傳過程中,後台伺服器需要確認該頭像文件是哪位用戶上傳的。前端在上傳文件時,一併將用戶id上傳至伺服器。伺服器需要確認該用戶是否已經登錄,只有登錄的用戶才有許可權上傳。最通常的做法是通過session來獲取用戶是否已經登錄,並進行許可權判斷。
Session功能集成
安裝session庫
go語言和gin框架都沒有實現session庫,可以通過第三方實現的session庫來集成session功能。安裝如下session庫:
go get github.com/gin-contrib/sessions
等待安裝完成,可以在$GOPATH/src/github.com/gin-contrib目錄下看到sessions庫。
初始化session
在項目中,集成session功能,首先要進行初始化。我們選擇將session數據持久化保存到redis中,因此需要與redis相結合。
新建SessionStore.go文件,並定義session初始化函數如下:
func InitSession() gin.HandlerFunc {
config := GetConfig().RedistConfig
SessionStore, _ := redis.NewStore(10, "tcp", config.Addr+":"+config.Port, config.Password, []byte("secret"))
return sessions.Sessions("onlinerestaurant", SessionStore)
}
通過redis.NewStore實例化sessionStore結構體對象,通過sessions.Sessions方法設置實例化後的sessionStore結構體對象。
封裝Session操作方法
session功能初始化完成以後就可以使用了,session的使用主要有兩個操作:set和get。在sessions庫中,有對應的session.Set(key, value)和session.Get(key)方法來實現set和get操作。
為了方便session的set和get操作,在初始化完session後,另外封裝session的set和get函數,具體實現如下:
//設置session
func SetSess(context *gin.Context, key interface{}, value interface{}) error {
session := sessions.Default(context)
if session == nil {
return nil
}
session.Set(key, value)
return session.Save()
}
//獲取session
func GetSess(context *gin.Context, key interface{}) interface{} {
session := sessions.Default(context)
if session == nil {
return nil
}
return session.Get(key)
}
用戶登錄添加session
當用戶進行登錄,並登錄成功後,選擇將用戶的資訊保存在session中。在項目的需要登錄才能使用的地方,可以進行許可權的判斷和攔截。
因此,在之前已經完成的登錄功能方法中,添加登錄操作成功後,將用戶數據保存到sesion的操作。在MemberController中的nameLogin和smsLogin方法中,添加如下設置session的程式碼操作,具體調用如下所示:
...
//設置session
sess, _ := json.Marshal(member)
err = tool.SetSess(context, "user_"+string(member.Id), sess)
if err != nil {
tool.Failed(context, "登錄失敗")
return
}
...
集成session操作
在項目的入口main.go文件的main函數中,通過中間件調用開啟session集成。main函數修改如下:
...
//集成session
app.Use(tool.InitSession())
...
文件上傳Contoller實現
在MemberController中,創建uploadAvator方法,用於實現用戶頭像上傳的業務流程式控制制。該方法其實主要有幾個步驟:第一步是獲取到用戶端上傳的文件,接下來將文件保存到對應的目錄中,因為要知道該文件對應的是哪位用戶的數據,因此需要將文件路徑更新到用戶資料庫中的對應記錄中:
//用戶頭像文件上傳
func (mc *MemberController) uploadAvator(context *gin.Context) {
//1、獲取上傳的文件
userId := context.Request.PostFormValue("user_id") //用戶id
file, header, err := context.Request.FormFile("avator")
if err != nil {
toolbox.Failed(context, "參數解析失敗")
return
}
//從session中獲取用戶資訊
sess := sessions.Default(context)
user := sess.Get(userId).(model.Member)
if user.Id == 0 {
toolbox.Failed(context, "參數不合法")
return
}
//2、將文件保存到本地
fileFullPath := "./uploadfile/" + header.Filename
out, err := os.Create(fileFullPath)
if err != nil {
toolbox.Error(err.Error())
return
}
defer out.Close()
_, err = io.Copy(out, file)
if err != nil {
toolbox.Error(err.Error())
return
}
//3、將文件對應路徑更新到資料庫中
memberService := impl.NewMemberService()
path := memberService.UploadAvator(user.Id, fileFullPath[1:])
if path != "" {
toolbox.Success(context, path)
return
}
toolbox.Failed(context, "上傳失敗")
Service層實現
在MemberService層實現UploadAvator方法,直接操作資料庫方法,完成數據記錄修改:
func (msi *MemberServiceImpl) UploadAvator(userid int64, path string) string {
dao := impl.NewMemberDao()
result := dao.UpdateMemberAvatar(userid, path)
if result == 0 {
return ""
}
return path
}
在service層,實現更新資料庫記錄的操作
資料庫操作層
在dao層,主要就是實現對資料庫表的操作:
func (mdi *MemberDaoImpl) UpdateMemberAvatar(userid int64, path string) int64 {
var member model.Member
result, err := mdi.Where(" id = ? ", userid).Update(&member,"avatar");
if err != nil {
toolbox.Error(err.Error())
}
return result
}
功能及背景介紹
上面完成了個人中心模組,用戶可以上傳圖片,修改並保存用戶頭像的功能。除此之外,在正常的開發中,也經常會有文件上傳的功能和需要。
在實際的開發中,涉及到文件上傳的功能,往往單獨搭建一個文件伺服器用於文件的存儲。因此我們接下來就搭建一個分散式的文件系統,並將已完成的文件上傳功能進行優化,將文件存儲到分散式文件系統中。
在本API項目中,我們通過搭建fastDFS文件系統來實現文件上傳和存儲的功能。
FastDFS介紹原理
FastDFS介紹,原理,分散式存儲介紹請看我寫的Fastdfs專篇
//www.cnblogs.com/you-men/p/12863555.html
FastDFS 單節點部署(5.09)
環境
[Fastdfs-Server]
主機名 = fastdfs-1
系統 = CentOS7.6.1810
地址 = 192.168.242.128
軟體 = libfastcommon-master
nginx-1.8.0.tar.gz
fastdfs_v5.05.tar.gz
fastdfs-nginx-module_v1.16.tar.gz
節點名 | IP | 軟體版本 | 硬體 | 網路 | 說明 |
---|---|---|---|---|---|
fastdfs | 192.168.242.128 | list 裡面都有 | 2C4G | Nat,內網 | 測試環境 |
安裝相關工具和依賴
yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim libevent -y
解壓編譯安裝
wget //github.com/happyfish100/libfastcommon/archive/master.zip
unzip master.zip
cd libfastcommon-master/
./make.sh && ./make.sh install
下載安裝FastDFS
wget //github.com/happyfish100/fastdfs/archive/V5.09.tar.gz
tar xf V5.09.tar.gz
cd fastdfs-5.09/
./make.sh && ./make.sh install
cp conf/http.conf /etc/fdfs/
cp conf/mime.types /etc/fdfs/
tracker配置
mkdir /home/fastdfs
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
vim /etc/fdfs/tracker.conf
#需要修改的內容如下
port=22122 # tracker伺服器埠(默認22122,一般不修改)
base_path=/home/fastdfs # 存儲日誌和數據的根目錄
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
storage配置
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
vim /etc/fdfs/storage.conf
#需要修改的內容如下
port=23000 # storage服務埠(默認23000,一般不修改)
base_path=/home/fastdfs # 數據和日誌文件存儲根目錄
store_path0=/home/fastdfs # 第一個存儲目錄
tracker_server=192.168.242.128:22122 # tracker伺服器IP和埠
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
安裝fastdfs-nginx-module
tar xf fastdfs-nginx-module_v1.16.tar.gz -C /usr/local
cd /usr/local/fastdfs-nginx-module/src/
cp mod_fastdfs.conf /etc/fdfs/
vim /etc/fdfs/mod_fastdfs.conf
base_path=/home/fastdfs
tracker_server=192.168.242.128:22122
url_have_group_name=true #url中包含group名稱
store_path0=/home/fdfs_storage #指定文件存儲路徑(上面配置的store路徑)
cp /usr/lib64/libfdfsclient.so /usr/lib/
配置nginx訪問
tar xv nginx-1.12.0.tar.gz
tar xf fastdfs-nginx-module_v1.16.tar.gz -C /usr/local
mkdir /usr/local/nginx
cd nginx-1.12.0/
./configure --prefix=/usr/local/nginx --add-module=/usr/local/fastdfs-nginx-module/src
make && make install
cp /usr/local/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
make && make install
mkdir /usr/local/nginx/logs # 創建logs目錄
cd /usr/local/nginx/conf/
vim nginx.conf
user root;
pid /usr/local/nginx/logs/nginx.pid;
server_name 192.168.242.128;
location /group1/M00/ {
root /home/fstdfs/data;
ngx_fastdfs_module;
}
此處可能會編譯報錯ngninx在gmake時可能出現找不到fdfs_define.h問題
錯誤資訊
root/fastdfs-nginx-module/src//common.c:21:25: fatal error:
fdfs_define.h: No such file or directory
#include "fdfs_define.h"
添加如下配置
# 把/usr/lib64/libfdfsclient.so庫拷貝到/usr/lib/目錄下:
# sudo cp /usr/lib64/libfdfsclient.so /usr/lib/
配置/usr/local/fastdfs-nginx-module/src/目錄下的config文件, 把CORE_INCS和CORE_LIBS的所有路徑都修改為/usr/include和/usr/lib:
vim /usr/local/src/fastdfs-nginx-module/src/config
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
CORE_LIBS="$CORE_LIBS -L/usr/lib -lfastcommon -lfdfsclient"
啟動tracker與storage
fdfs_storaged /etc/fdfs/storage.conf start
fdfs_trackerd /etc/fdfs/tracker.conf start
/usr/local/nginx/sbin/nginx
配置client上傳文件測試
vim /etc/fdfs/client.conf
#需要修改的內容如下
base_path=/home/fastdfs
tracker_server=192.168.242.128:22122
[root@tracker1 sbin]# fdfs_test /etc/fdfs/client.conf upload /root/1.jpg
This is FastDFS client test program v5.05
Copyright (C) 2008, Happy Fish / YuQing
FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.
Please visit the FastDFS Home Page //www.csource.org/
for more detail.
[2020-07-17 00:00:50] DEBUG - base_path=/home/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
tracker_query_storage_store_list_without_group:
server 1. group_name=, ip_addr=192.168.242.128, port=23000
group_name=group1, ip_addr=192.168.242.128, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/wKjygF8QebKAWJCPAADMPhWBDxw409.jpg
source ip address: 192.168.242.128
file timestamp=2020-07-17 00:00:50
file size=52286
file crc32=360779548
example file url: //192.168.242.128/group1/M00/00/00/wKjygF8QebKAWJCPAADMPhWBDxw409.jpg
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/wKjygF8QebKAWJCPAADMPhWBDxw409_big.jpg
source ip address: 192.168.242.128
file timestamp=2020-07-17 00:00:50
file size=52286
file crc32=360779548
example file url: //192.168.242.128/group1/M00/00/00/wKjygF8QebKAWJCPAADMPhWBDxw409_big.jpg
今晚更新中