golang自动处理HTTP文件上传需求的中间件插件gulter的使用
Golang自动处理HTTP文件上传需求的中间件插件gulter的使用
Gulter是一个Go HTTP中间件,旨在简化Web应用程序的文件上传过程。它遵循标准的http.Handler
和http.HandlerFunc
接口,因此可以与任何框架或标准库路由器一起使用。
安装
go get -u -v github.com/adelowo/gulter
使用
假设您有一个HTML表单如下:
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="form-field-1" />
<input type="file" name="form-field-2" />
</form>
要创建一个新的Gulter实例,可以这样做:
handler, _ := gulter.New(
gulter.WithMaxFileSize(10<<20), // 设置最大文件大小为10MB
gulter.WithValidationFunc( // 设置验证函数
gulter.ChainValidators(gulter.MimeTypeValidator("image/jpeg", "image/png"), // 验证MIME类型
func(f gulter.File) error {
// 这里可以添加自定义的文件验证逻辑
// 也可以只使用MimeTypeValidator或单独使用一个自定义验证器
return nil
})),
gulter.WithStorage(s3Store), // 设置存储后端
)
handler
实际上是一个HTTP中间件,具有以下签名:Upload(keys ...string) func(next http.Handler) http.Handler
。这里的keys
是HTML表单中的输入名称,因此您可以将其链接到几乎任何HTTP路由器中。
标准HTTP路由器示例
package main
import (
"fmt"
"net/http"
"github.com/adelowo/gulter"
"github.com/adelowo/gulter/storage"
)
func main() {
s3Store, err := storage.NewS3FromEnvironment(storage.S3Options{
Bucket: "std-router",
})
if err != nil {
panic(err.Error())
}
handler, err := gulter.New(
gulter.WithMaxFileSize(10<<20), // 10MB
gulter.WithStorage(s3Store),
)
mux := http.NewServeMux()
// 上传表单字段名为"name"和"lanre"的所有文件
mux.Handle("/", handler.Upload("name", "lanre")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Uploaded file")
// 获取所有上传的文件
f, err := gulter.FilesFromContext(r)
if err != nil {
fmt.Println(err)
return
}
// 获取表单字段"lanre"的上传文件
ff, err := gulter.FilesFromContextWithKey(r, "lanre")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", ff)
for _, v := range f {
fmt.Printf("%+v", v)
fmt.Println()
}
})))
http.ListenAndServe(":3300", mux)
}
Chi路由器和其他兼容HTTP处理程序示例
s3Store, err := storage.NewS3FromEnvironment(storage.S3Options{
Bucket: "chi-router",
})
if err != nil {
panic(err.Error())
}
handler := gulter.New(
gulter.WithMaxFileSize(10<<20), // 10MB
gulter.WithValidationFunc(gulter.ChainValidators(gulter.MimeTypeValidator("image/jpeg", "image/png"))),
gulter.WithStorage(s3Store),
)
router := chi.NewMux()
// 上传表单字段名为"form-field-1"和"form-field-2"的所有文件
router.With(handler.Upload("form-field-1", "form-field-2")).Post("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Uploaded file")
f, err := gulter.FilesFromContext(r)
if err != nil {
fmt.Println(err)
return
}
ff, err := gulter.FilesFromContextWithKey(r, "form-field-1") // 或者form-field-2
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", ff)
for _, v := range f {
fmt.Printf("%+v", v)
fmt.Println()
}
})
API
虽然这个中间件会自动上传您的文件,但有时您需要有关上传文件的详细信息以显示给用户,这可能是组成图像URL或图像路径。要在HTTP处理程序中获取这些信息,您可以使用:
FilesFromContextWithKey
: 检索指定输入名称的上传文件FilesFromContext
: 检索所有上传的文件
Gulter目前还提供了两种存储实现:
S3Store
: 支持S3或任何兼容服务,如Minio、R2等DiskStore
: 使用本地文件系统支持的存储来上传文件CloudinaryStore
: 将文件上传到Cloudinary
常见问题
忽略多部分请求中不存在的键
有时,您配置的中间件键可能会因某种原因从前端删除,理想情况下,如果中间件无法在请求中找到配置的键,则会失败。要禁用此行为并忽略缺少的键,您可以使用WithIgnoreNonExistentKey(true)
选项来防止中间件在缺少这些键时引发错误。
自定义错误响应
由于Gulter是一个运行的中间件,如果发现错误,它会向客户端返回错误,这可能与您现有的结构不匹配,因此要配置响应,请使用WithErrorResponseHandler
。默认如下所示,可以用作定义您自己的模板。
errHandler ErrResponseHandler = func(err error) http.HandlerFunc {
return func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, `{"message" : "could not upload file", "error" : %s}`, err.Error())
}
}
编写自定义验证逻辑
有时,您可能有一些自定义逻辑来验证上传,在下面的示例中,我们根据上传文件的MIME类型限制上传的大小。
var customValidator gulter.ValidationFunc = func(f gulter.File) error {
switch f.MimeType {
case "image/png":
if f.Size > 4096 {
return errors.New("file size too large")
}
return nil
case "application/pdf":
if f.Size > (1024 * 10) {
return errors.New("file size too large")
}
return nil
default:
return nil
}
}
更多关于golang自动处理HTTP文件上传需求的中间件插件gulter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang自动处理HTTP文件上传需求的中间件插件gulter的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang HTTP文件上传中间件gulter使用指南
gulter是一个轻量级的Golang中间件,用于简化HTTP文件上传处理。下面我将详细介绍如何使用gulter处理文件上传需求。
安装gulter
首先安装gulter包:
go get github.com/thewizardplusplus/go-gulter
基本用法
package main
import (
"fmt"
"log"
"net/http"
"github.com/thewizardplusplus/go-gulter"
)
func main() {
// 创建gulter中间件实例
uploadMiddleware := gulter.New(gulter.Config{
// 上传文件存储目录
UploadDir: "./uploads",
// 允许的最大文件大小(字节)
MaxFileSize: 10 << 20, // 10MB
// 允许的MIME类型
AllowedMimeTypes: []string{
"image/jpeg",
"image/png",
"application/pdf",
},
})
// 创建HTTP处理函数
uploadHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 从上下文中获取上传的文件信息
files, ok := r.Context().Value(gulter.UploadedFilesContextKey).([]gulter.UploadedFile)
if !ok {
http.Error(w, "no files uploaded", http.StatusBadRequest)
return
}
// 处理上传的文件
for _, file := range files {
fmt.Fprintf(w, "File uploaded: %s, Size: %d, MIME: %s\n",
file.Filename, file.Size, file.MimeType)
}
})
// 应用中间件
http.Handle("/upload", uploadMiddleware(uploadHandler))
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
高级配置
gulter提供了多种配置选项:
uploadMiddleware := gulter.New(gulter.Config{
UploadDir: "./uploads",
MaxFileSize: 5 << 20, // 5MB
AllowedMimeTypes: []string{"image/*"}, // 允许所有图片类型
FieldName: "custom_file_field", // 默认是"file"
RandomFilename: true, // 生成随机文件名
Overwrite: false, // 不允许覆盖已有文件
Multiple: true, // 允许多文件上传
})
文件验证
你可以在处理函数中添加自定义验证:
uploadHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
files, ok := r.Context().Value(gulter.UploadedFilesContextKey).([]gulter.UploadedFile)
if !ok {
http.Error(w, "no files uploaded", http.StatusBadRequest)
return
}
for _, file := range files {
// 自定义验证逻辑
if file.Size > 2<<20 { // 2MB
http.Error(w, fmt.Sprintf("file %s is too large", file.Filename), http.StatusBadRequest)
return
}
// 处理文件...
}
})
错误处理
gulter会返回详细的错误信息:
uploadHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err, ok := r.Context().Value(gulter.UploadErrorContextKey).(error); ok {
switch err {
case gulter.ErrNoFileUploaded:
http.Error(w, "请选择要上传的文件", http.StatusBadRequest)
case gulter.ErrFileTooLarge:
http.Error(w, "文件大小超过限制", http.StatusBadRequest)
case gulter.ErrInvalidFileType:
http.Error(w, "不支持的文件类型", http.StatusBadRequest)
default:
http.Error(w, "上传文件时出错", http.StatusInternalServerError)
}
return
}
// 正常处理...
})
完整示例
下面是一个完整的文件上传服务示例:
package main
import (
"fmt"
"log"
"net/http"
"os"
"github.com/thewizardplusplus/go-gulter"
)
func main() {
// 确保上传目录存在
if err := os.MkdirAll("./uploads", 0755); err != nil {
log.Fatal(err)
}
// 配置gulter中间件
uploadMiddleware := gulter.New(gulter.Config{
UploadDir: "./uploads",
MaxFileSize: 5 << 20, // 5MB
AllowedMimeTypes: []string{"image/jpeg", "image/png"},
RandomFilename: true,
})
// 上传处理函数
uploadHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 检查错误
if err, ok := r.Context().Value(gulter.UploadErrorContextKey).(error); ok {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 获取上传的文件
files, ok := r.Context().Value(gulter.UploadedFilesContextKey).([]gulter.UploadedFile)
if !ok || len(files) == 0 {
http.Error(w, "没有上传文件", http.StatusBadRequest)
return
}
// 返回上传结果
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
for _, file := range files {
fmt.Fprintf(w, `{"filename": "%s", "size": %d, "mime": "%s"}\n`,
file.Filename, file.Size, file.MimeType)
}
})
// 文件下载处理
http.HandleFunc("/download/", func(w http.ResponseWriter, r *http.Request) {
filename := r.URL.Path[len("/download/"):]
http.ServeFile(w, r, "./uploads/"+filename)
})
// 上传路由
http.Handle("/upload", uploadMiddleware(uploadHandler))
// 静态文件服务
fs := http.FileServer(http.Dir("./static"))
http.Handle("/", fs)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
总结
gulter是一个功能强大且易于使用的Golang文件上传中间件,它提供了:
- 文件大小限制
- MIME类型验证
- 多文件上传支持
- 随机文件名生成
- 详细的错误处理
- 简单的集成方式
通过合理配置,你可以轻松地为你的Golang Web应用添加安全可靠的文件上传功能。