这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
Golang 文件上传
为了文章的整洁主要使用 Hertz 实现,其它框架可以查看这个网站是否有对应的代码:
基本流程就是从请求的表单(DataForm)中获取 mulitpart.FileHeader 对象,然后通过 Open 方法获取实现了 Reader 接口的 mulitpart.File 对象,之后再进行对象存储上传或者文件保存操作
代码
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default()
h.POST("/upload", func(ctx context.Context, req *app.RequestContext) {
header, err := req.FormFile("file")
if err != nil {
req.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
return
}
filename := header.Filename
log.Println(filename)
// TODO 处理
req.String(http.StatusOK, fmt.Sprintf("%s uploaded!", filename))
})
h.Spin()
}
将文件转为 byte 切片
可以通过创建一个 byte 切片,然后使用 Read 循环读取,也可以直接使用 io 包中提供的 Copy 方法,直接 Copy 到 bytes.Buffer 中,使用 Bytes() 获取整个文件的 byte 切片
file := header.Open()
defer file.Clone() // 这里可以处理一下关闭错误
buff := new(bytes.Buffer)
written, err := io.Copy(buff, file) // written 复制的字节数,err 复制过程中的错误
buff.Bytes()
文件类型验证
这里使用 github.com/h2non/filet… 库
// 使用文件头验证
head := make([]byte, 261)
_, err = file.Read(head)
if err != nil {
return
}
// 这里检查是否是视频格式
if !filetype.IsVideo(head) {
err = errno.AuthorizationFailedErr
return
}
// 将偏移设置到文件开头
_, err = file.Seek(0, io.SeekStart)
if err != nil {
return
}
支持的类型
- Image
- Video
- Audio
- Archive
- Documents
- Font
- Application
详细的支持列表:Supported Types
所有的自带的支持类型都在 github.com/h2non/filet… 当中,这些类型都注册到了 filetype 中,使用 func Match(buf []byte) (types.Type, error) 函数会返回匹配的文件类型
match, err := filetype.Match(head)
if err != nil {
// TODO Error Handler
}
if match == filetype.Unknown {
// TODO Unknown Type
}
// TODO Other Type