基于gin框架的文件上傳(逐行解析)
記錄一下使用gin框架完成一個文件上傳的功能,一下是實現該功能的代碼,適合小白,代碼都有逐行解釋!
app.go
:
package routerimport ("chat/service""github.com/gin-gonic/gin"
)func Router() *gin.Engine {r := gin.Default()//上傳文件,使用post請求r.POST("/attach/upload", service.Upload)return r
}
attach.go
:
package serviceimport ("chat/utils""fmt""github.com/gin-gonic/gin""io""math/rand""net/http""os""strings""time"
)func Upload(c *gin.Context) {UploadLocal(c)
}// 上傳文件到本地
func UploadLocal(c *gin.Context) {w := c.Writer //獲取響應的gin上下文寫入器req := c.Request//獲取當前請求對象//從請求中通過FormFile方方法獲取指定名稱("file")的文件//srcFile為獲取到的源文件//head為文件的頭部信息//err為可能出現的錯誤srcFile, head, err := req.FormFile("file") if err != nil {//使用utils.RespFail()函數響應寫入失敗信息和錯誤內容utils.RespFail(w, err.Error())}
//定義默認的文件后綴為".png"suffix := ".png"//從head中獲取文件信息head有以下常用變量//head.Header 文件的頭部信息,包含一些與文件相關的元數據,比如文件的類型、大小//head.Size 文件的大小//head.Filename 文件的名字ofilName := head.Filename //定義一個字符串切片tem,使用strings。Split()將文件名ofilName按照(.)進行分割再裝入這個切片當中,tem := strings.Split(ofilName, ".")//如果分割后的結果長度大于1,表示有后綴if len(tem) > 1 {// 將后綴更新為分割后的最后一部分(該切片的最后一個元素)suffix = "." + tem[len(tem)-1]}// 根據當前時間的 Unix 時間戳、隨機生成的 32 位整數和后綴生成文件名fileName := fmt.Sprintf("%d%04d%s", time.Now().Unix(), rand.Int31(), suffix)//使用os.Create()在指定路徑("./files/"+fileName)創建新的文件dstFile, err := os.Create("./files/" + fileName)if err != nil {//使用utils.RespFail()函數響應寫入失敗信息和錯誤內容utils.RespFail(w, err.Error())}// 使用 io.Copy 方法將源文件的內容拷貝到目標文件中// err 為可能出現的拷貝過程中的錯誤_, err = io.Copy(dstFile, srcFile)if err != nil {//使用utils.RespFail()函數響應寫入失敗信息和錯誤內容utils.RespFail(w, err.Error())}//構建文件的完整的URLurl := "./files/" + fileName// 使用 utils.RespOK 函數向響應寫入成功信息、文件的 URL 以及成功消息utils.RespOK(w, url, "發送成功")
}
resp.go
:主要用處理請求響應的各種狀態
package utilsimport (// 導入相關包"encoding/json""fmt""net/http"
)type H struct {// 定義結構體 H,包含代碼、消息、數據、行數和總數等字段Code intMsg stringData interface{}Rows interface{}Total interface{}
}// Resp 函數,用于響應數據
func Resp(w http.ResponseWriter, code int, data interface{}, msg string) {// 設置響應頭的內容類型為 JSONw.Header().Set("Content-Type", "application/json")// 設置響應狀態碼為 200(OK)w.WriteHeader(http.StatusOK)h := H{// 初始化結構體 H 的字段Code: code,Data: data,Msg: msg,}// 對結構體 H 進行 JSON 序列化操作ret, err := json.Marshal(h)if err!= nil {// 處理序列化錯誤fmt.Println(err)}w.Write(ret)
}// RespList 函數,用于響應列表數據
func RespList(w http.ResponseWriter, code int, data interface{}, total interface{}) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)h := H{// 初始化結構體 H 的字段Code: code,Rows: data,Total: total,}ret, err := json.Marshal(h)if err!= nil {// 處理序列化錯誤fmt.Println(err)}w.Write(ret)
}// RespFail 函數,用于響應失敗信息
func RespFail(w http.ResponseWriter, msg string) {// 調用 Resp 函數,設置代碼為-1,表示失敗Resp(w, -1, nil, msg)
}// RespOK 函數,用于響應成功信息
func RespOK(w http.ResponseWriter, data interface{}, msg string) {// 調用 Resp 函數,設置代碼為 0,表示成功Resp(w, 0, data, msg)
}// RespOKList 函數,用于響應成功的列表信息
func RespOKList(w http.ResponseWriter, data interface{}, total int) {// 調用 RespList 函數,設置代碼為 0,表示成功RespList(w, 0, data, total)
}
main.go
:
package mainimport "chat/router"func main() {r := router.Router()r.Run(":8081")
}
寫完了:測試一下
使用postman提交一個文件參數
查看是否上傳成功
可以看到文件上傳成功了!