Golang使用Gin實現(xiàn)文件上傳的示例代碼
前言
今天我們來聊聊如何使用Gin實現(xiàn)文件上傳。
Go標準庫net/http對文件上傳已經(jīng)提供了非常完善的支持,而Gin框架在其基礎上進一步封裝,因此使用Gin開發(fā)文件上傳功能時,只需要簡單幾行代碼便可以實現(xiàn),Gin框架支持單個文件與多個文件同時上傳。
使用原生net/http庫實現(xiàn)文件上傳
我們首先看看實現(xiàn)一個HTTP服務器,提供文件上傳功能的簡單示例
package main
import (
"io"
"io/ioutil"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
const (
MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上傳大小,50MB
)
func main() {
r := RegisterHandlers()
http.ListenAndServe(":8080", r) // 開啟一個http服務
}
// 定義路由
func RegisterHandlers() *httprouter.Router {
router := httprouter.New()
router.POST("/upload", uploadHandler)
return router
}
// 文件上傳接口
func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)
if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
log.Printf("File is too big")
return
}
file, headers, err := r.FormFile("file")
if err != nil {
log.Printf("Error when try to get file: %v", err)
return
}
//獲取上傳文件的類型
if headers.Header.Get("Content-Type") != "image/png" {
log.Printf("只允許上傳png圖片")
return
}
data, err := ioutil.ReadAll(file)
if err != nil {
log.Printf("Read file error: %v", err)
return
}
fn := headers.Filename
err = ioutil.WriteFile("./video/"+fn, data, 0666)
if err != nil {
log.Printf("Write file error: %v", err)
return
}
w.WriteHeader(http.StatusCreated)
io.WriteString(w, "Uploaded successfully")
}如上我們通過r.FormFile函數(shù)獲取上傳的文件對象,以及文件的相關信息。然后通過headers.Header.Get函數(shù)獲取上傳文件的類型,判斷類型是否符合要求。接著,使用ioutil.ReadAll函數(shù)讀取文件的內(nèi)容,并將其存儲在data變量中。然后,通過headers.Filename獲取上傳文件的文件名,并使用ioutil.WriteFile函數(shù)將文件內(nèi)容寫入到指定路徑下的文件中。
使用Gin實現(xiàn)文件上傳
單個文件上傳
FormFile()獲取文件
單文件上傳使用gin.Context的FormFile()方法,該方法的值為POST請求中文件上傳字段的名稱:
engine := gin.Default()
engine.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
})
engine.Run()SaveUploadedFile()保存到本地
調(diào)用gin.Context的SaveUploadedFile()方法可以將文件保存到某個目錄下:
dst := "./uploads/" + file.Filename c.SaveUploadedFile(file,"./uploadFile")
設置緩沖區(qū)大小
Go默認文件上傳緩沖區(qū)為32M,當有大量文件上傳時,服務器內(nèi)存的壓力會很大,因此可以通過MaxMultipartMemory屬性來設置緩沖區(qū)大小:
//8M engine.MaxMultipartMemory = 8 << 20
限制文件大小
上傳文件時,不限制文件大小可以會導致服務存儲空間暴漲,因為有必須限制上傳文件大?。?/p>
fileMaxSize := 4 << 20 //4M
if int(file.Size) > fileMaxSize {
c.String(http.StatusBadRequest, "文件不允許大小于4M")
return
}限制文件類型
對文件類型,也可以進行限制:
reader, err := file.Open()
if err != nil {
fmt.Println(err)
return
}
b := make([]byte, 512)
reader.Read(b)
?
contentType := http.DetectContentType(b)
if contentType != "image/jpeg" && contentType != "image/png" {
c.String(http.StatusOK, "文件格式錯誤")
return
}在上面的代碼中,我們讀取文件的前512個字節(jié),再調(diào)用http.DetectContentType()便可以獲取文件的MIME值。
完整示例
package main
?
import (
"fmt"
"log"
"net/http"
?
"github.com/gin-gonic/gin"
)
?
func main() {
engine := gin.Default()
//8M
engine.MaxMultipartMemory = 8 << 20
engine.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
log.Println(err)
c.String(http.StatusBadRequest, "文件上傳失敗")
return
}
fileMaxSize := 4 << 20 //4M
if int(file.Size) > fileMaxSize {
c.String(http.StatusBadRequest, "文件不允許大小于32KB")
return
}
?
reader, err := file.Open()
if err != nil {
fmt.Println(err)
return
}
b := make([]byte, 512)
reader.Read(b)
?
contentType := http.DetectContentType(b)
if contentType != "image/jpeg" && contentType != "image/png" {
c.String(http.StatusOK, "文件格式錯誤")
return
}
?
dst := "./uploads/" + file.Filename
c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' 上傳成功!", file.Filename))
})
engine.Run()
}
?測試文件上傳
$ curl -F "file=@./1.jpg" -X POST "http://localhost:8080/upload" '1.jpg' 上傳成功!
多個文件上傳
MultipartForm()獲取多個文件
如果要上傳多個文件,多次調(diào)用gin.Context的FormFile()方法也是可以的,但更好的方式是使用gin.Context的MultipartForm()方法:
package main
?
import (
"fmt"
"log"
"net/http"
?
"github.com/gin-gonic/gin"
)
?
func main() {
engine := gin.Default()
engine.POST("/uploadMul", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
log.Println(err)
c.String(http.StatusBadRequest, "文件上傳失敗")
return
}
files := form.File["upload"]
for _, file := range files {
fmt.Println(file.Filename)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
engine.Run()
}測試文件上傳
運行程序后,使用curl命令上傳多個文件:
$ curl -F "upload=@./1.jpg" -F "upload=@./2.jpg" -X POST "http://localhost:8080/uploadMul 2 files uploaded
總結
Go標準庫net/http對文件上傳已經(jīng)提供了非常完善的支持,可以滿足我們大部分需求,Gin框架在其基礎做了封裝,讓我們使用起來更加方便迅速。
以上就是Golang使用Gin實現(xiàn)文件上傳的示例代碼的詳細內(nèi)容,更多關于Golang Gin文件上傳的資料請關注腳本之家其它相關文章!
相關文章
golang中range在slice和map遍歷中的注意事項
今天小編就為大家分享一篇關于golang中range在slice和map遍歷中的注意事項,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04
go語言題解LeetCode1299將每個元素替換為右側最大元素
這篇文章主要為大家介紹了go語言LeetCode刷題1299將每個元素替換為右側最大元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01
golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法
這篇文章主要介紹了golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
golang struct擴展函數(shù)參數(shù)命名警告解決方法
今天在使用VSCode編寫golang代碼時,定義一個struct,擴展幾個方法,需要的朋友可以參考下2017-02-02
golang 定時任務方面time.Sleep和time.Tick的優(yōu)劣對比分析
這篇文章主要介紹了golang 定時任務方面time.Sleep和time.Tick的優(yōu)劣對比分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05

