概述
如何使用 GoFrame 规范路由实现上传一个压缩包(例如 zip 格式)并解压出其中的图片文件进行处理。示例分为两个部分:路由注册和处理函数代码。
1. 路由注册
假设项目结构中有一个 router
包,用于统一注册路由。在这里,我们注册一个 POST 请求路由 /upload/zip
,指向处理上传的控制器方法。例如:
// router/router.go package router import ( "myproject/app/api" // 替换为你自己的包路径 "github.com/gogf/gf/v2/net/ghttp" ) func init() { // 获取默认服务对象 s := ghttp.GetServer() // 这里可以使用分组路由,方便后续扩展 s.Group("/", func(group *ghttp.RouterGroup) { // 定义 POST 路由,处理压缩包上传 group.POST("/upload/zip", api.Upload.UploadZip) }) }
2. 上传处理函数
在处理函数中,我们需要:
从请求中获取上传的文件(假设表单字段名称为
file
)。将上传文件保存到临时目录。
使用 Go 内置的
archive/zip
包打开压缩包。遍历压缩包内的所有文件,筛选出图片文件(通过后缀名判断),并保存到指定目录或进行进一步处理。
下面是示例代码:
// app/api/upload/upload.go package upload import ( "archive/zip" "io" "os" "path/filepath" "strings" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" ) // Upload 对象,可以在此处添加更多相关方法 var Upload = new(uploadApi) type uploadApi struct{} // UploadZip 处理上传压缩包并解压出图片 func (a *uploadApi) UploadZip(r *ghttp.Request) { // 1. 从请求中获取上传的文件,字段名称为 "file" uploadFile := r.GetUploadFile("file") if uploadFile == nil { r.Response.WriteJson(g.Map{"code": 400, "msg": "未获取到上传文件"}) return } // 2. 保存上传文件到临时目录 tempDir := "./uploads/temp" if err := os.MkdirAll(tempDir, os.ModePerm); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "创建临时目录失败:" + err.Error()}) return } tempFilePath := filepath.Join(tempDir, uploadFile.Filename) if err := uploadFile.Save(tempFilePath); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "保存上传文件失败:" + err.Error()}) return } // 3. 打开压缩包 zipReader, err := zip.OpenReader(tempFilePath) if err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "打开压缩包失败:" + err.Error()}) return } defer zipReader.Close() // 4. 创建存放图片的目标目录 imgDir := "./uploads/images" if err := os.MkdirAll(imgDir, os.ModePerm); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "创建图片目录失败:" + err.Error()}) return } // 5. 遍历压缩包内的所有文件 for _, f := range zipReader.File { // 判断文件后缀是否为图片(可根据需求扩展) if !isImage(f.Name) { continue } // 打开压缩包内的文件 rc, err := f.Open() if err != nil { g.Log().Errorf(r.Context(), "打开文件[%s]失败:%v", f.Name, err) continue } // 拼接目标文件路径,取文件名部分(防止目录穿越) targetPath := filepath.Join(imgDir, filepath.Base(f.Name)) outFile, err := os.Create(targetPath) if err != nil { g.Log().Errorf(r.Context(), "创建目标文件[%s]失败:%v", targetPath, err) rc.Close() continue } // 拷贝文件内容到目标文件 if _, err := io.Copy(outFile, rc); err != nil { g.Log().Errorf(r.Context(), "保存文件[%s]失败:%v", targetPath, err) outFile.Close() rc.Close() continue } outFile.Close() rc.Close() } // 6. 返回成功响应 r.Response.WriteJson(g.Map{"code": 200, "msg": "上传并处理成功"}) } // isImage 判断文件是否为图片,根据扩展名判断 func isImage(filename string) bool { ext := strings.ToLower(filepath.Ext(filename)) switch ext { case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp": return true } return false }
3.使用规范路由
(1). 路由绑定(规范路由)
在项目的路由注册文件中,我们使用 BindObject
绑定控制器对象到指定路由。例如:
// router/router.go package router import ( "myproject/app/api/upload" // 请根据实际项目路径调整 "github.com/gogf/gf/v2/net/ghttp" ) func init() { // 获取默认的 HTTP 服务对象 s := ghttp.GetServer() // 将 Upload 控制器绑定到 /upload 路径 // 这样,当请求 /upload/zip 时,将自动调用 Upload 对象中的 Zip 方法 s.BindObject("/upload", new(upload.Upload)) }
(2). 控制器方法实现
在控制器对象中定义一个 Zip
方法,该方法将会自动映射到路由 /upload/zip
。实现步骤如下:
获取上传文件:从请求中取出上传的文件(表单字段名称为
file
)。保存上传文件到临时目录:用于后续打开解压。
使用
archive/zip
包打开压缩包。遍历压缩包中文件:筛选出图片文件(通过后缀判断),并保存到指定目录中。
返回处理结果。
示例代码如下:
// app/api/upload/upload.go package upload import ( "archive/zip" "io" "os" "path/filepath" "strings" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" ) // Upload 控制器对象,通过规范路由绑定后自动映射 URL 请求 type Upload struct{} // Zip 方法处理 /upload/zip 请求,实现压缩包上传及图片处理 func (u *Upload) Zip(r *ghttp.Request) { // 1. 从请求中获取上传文件,字段名称为 "file" uploadFile := r.GetUploadFile("file") if uploadFile == nil { r.Response.WriteJson(g.Map{"code": 400, "msg": "未获取到上传文件"}) return } // 2. 保存上传文件到临时目录 tempDir := "./uploads/temp" if err := os.MkdirAll(tempDir, os.ModePerm); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "创建临时目录失败:" + err.Error()}) return } tempFilePath := filepath.Join(tempDir, uploadFile.Filename) if err := uploadFile.Save(tempFilePath); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "保存上传文件失败:" + err.Error()}) return } // 3. 打开上传的 zip 压缩包 zipReader, err := zip.OpenReader(tempFilePath) if err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "打开压缩包失败:" + err.Error()}) return } defer zipReader.Close() // 4. 创建存放图片的目标目录 imgDir := "./uploads/images" if err := os.MkdirAll(imgDir, os.ModePerm); err != nil { r.Response.WriteJson(g.Map{"code": 500, "msg": "创建图片目录失败:" + err.Error()}) return } // 5. 遍历压缩包内的所有文件 for _, f := range zipReader.File { // 根据扩展名判断是否为图片文件 if !isImage(f.Name) { continue } // 打开压缩包内的文件 rc, err := f.Open() if err != nil { g.Log().Errorf(r.Context(), "打开文件[%s]失败:%v", f.Name, err) continue } // 防止目录穿越:只取文件名部分 targetPath := filepath.Join(imgDir, filepath.Base(f.Name)) outFile, err := os.Create(targetPath) if err != nil { g.Log().Errorf(r.Context(), "创建目标文件[%s]失败:%v", targetPath, err) rc.Close() continue } // 将压缩包中文件内容拷贝到目标文件 if _, err := io.Copy(outFile, rc); err != nil { g.Log().Errorf(r.Context(), "保存文件[%s]失败:%v", targetPath, err) outFile.Close() rc.Close() continue } outFile.Close() rc.Close() } // 6. 返回成功响应 r.Response.WriteJson(g.Map{"code": 200, "msg": "上传并处理成功"}) } // isImage 判断文件是否为图片文件(可根据需求扩展判断规则) func isImage(filename string) bool { ext := strings.ToLower(filepath.Ext(filename)) switch ext { case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp": return true } return false }
(3). 说明
规范路由:使用
s.BindObject("/upload", new(upload.Upload))
后,框架会自动将请求/upload/zip
映射到Upload
对象的Zip
方法,无需手动编写路由分组或具体路由映射。安全性:
文件保存时使用
filepath.Base
只获取文件名,避免目录穿越风险。可根据实际需要增加对文件大小、MIME 类型等校验。
扩展:除了基础的图片文件保存,实际项目中还可以对图片做缩略图处理、水印添加、上传到云存储等操作。
以上示例展示了如何使用 GoFrame 规范路由实现图片压缩包的上传与处理。根据项目实际需求,你可以进一步完善错误处理和业务逻辑。
最后
以上就是岁月静好为你收集整理的使用 goframe 框架的规范路由进行图片文件压缩包的上传与处理的全部内容,希望文章能够帮你解决使用 goframe 框架的规范路由进行图片文件压缩包的上传与处理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复