9、Go Gin 文件上传

参考:单文件 | Gin Web Framework参考 issue #774 和详细示例代码.func main() {router := gin.Default()// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)router.MaxMultipartMemory = 8 << 20 …icon-default.png?t=N7T8https://gin-gonic.com/zh-cn/docs/examples/upload-file/single-file/

在Go语言中,使用Gin框架处理文件上传是一个相对直接的过程。Gin框架内置了对multipart/form-data类型请求的支持,这是Web上传文件时常用的编码类型。下面是一个简单的示例,展示如何使用Gin来接收并保存上传的文件。 

1、单文件上传

官方示例重现

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	// 设置上传的路由和处理函数
	r.POST("/upload", func(c *gin.Context) {
		// 单文件上传
		file, err := c.FormFile("file") //此方法会返回一个multipart.FileHeader对象,包含了上传文件的相关信息
		if err != nil {
			c.String(400, fmt.Sprintf("上传文件出错:%s", err.Error()))
			return
		}

		// 指定文件保存的路径,
		dst := "./uploads/" + file.Filename
		// 保存上传的文件到指定的目录,你需要确保该目录事先已存在,否则会引发错误
		err = c.SaveUploadedFile(file, dst)
		if err != nil {
			c.String(500, fmt.Sprintf("保存文件出错:%s", err.Error()))
			return
		}

		c.String(200, fmt.Sprintf("文件'%s'上传成功!", file.Filename))
	})

	// 启动服务器
	//然后,你可以使用Postman或者curl等工具向http://localhost:8080/upload发送POST请求,并附上要上传的文件(确保Content-Type设置为multipart/form-data且表单字段名与代码中一致,这里是"file")
	r.Run(":8080")
}

注意事项

  • 确保服务器有权限写入指定的文件保存目录。
  • 根据需要处理文件大小限制、文件类型验证等安全措施,以防止恶意文件上传。
  • 实际应用中可能还需要考虑并发访问、文件命名冲突等问题。

2、项目中实现单文件上传 

(1)、项目结构

(2)、定义模板

需要在上传文件的 form 表单上面需要加入 enctype="multipart/form-data" 

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/user/add.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{.title}}</title>
</head>
<body>
<h2>演示文件上传</h2>
<form action="/admin/user/DoUpload" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username" placeholder="用户名"><br/><br/>
    头像: <input type="file" name="face"><br/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>
{{ end }}

(3)、定义业务控制类 

package admin

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"path"
)

type UserController struct {
}

// Add 添加:单文件上传
// http://localhost:8080/admin/user/Add
func (con UserController) Add(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/user/add.html", gin.H{
		"title": "单文件上传",
	})
}

// DoUpload 单文件上传
func (con UserController) DoUpload(c *gin.Context) {
	//获取表单中提交的username
	username := c.PostForm("username")
	//获取文件
	file, err := c.FormFile("face")
	//判断上传文件上否存在
	if err != nil { //说明上传文件不存在
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": err.Error(),
		})
		return
	}
	//设置需要上传的文件目录 file.Filename 获取文件名; "./static/upload" 是基于main.go文件路由的
	dst := path.Join("./static/upload", file.Filename)
	//上传文件到指定目录
	c.SaveUploadedFile(file, dst)
	c.JSON(http.StatusOK, gin.H{
		"success":  "true",
		"username": username,
		"dst":      dst,
	})
}

 (4)、定义路由配置

package routers

import (
	"gin-mall/controllers/admin"
	"gin-mall/middlewares"
	"github.com/gin-gonic/gin"
)

// 设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
	//路由分组: 配置全局中间件:middlewares.InitMiddleware
	adminRouters := r.Group("/admin", middlewares.InitMiddleware)
	{
		adminRouters.GET("user/Add", admin.UserController{}.Add)
		//单文件上传
		adminRouters.POST("/user/DoUpload", admin.UserController{}.DoUpload)
	}
}
  (5)、主入口
package main

import (
	"gin-mall/routers"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("templates/**/**/*")//templates下有多少层目录就有多少个"/**"
	routers.AdminRoutersInit(r)
	r.Run(":8080")
}

 3、项目中实现多文件上传(同名覆盖)

  (1)、项目结构

 

  (2)、定义模板 
<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/user/addnotfilenameupload.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{.title}}</title>
</head>
<body>
<h2>演示不同文件名的文件上传</h2>
<form action="/admin/user/DoNotFileNameUploads" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username" placeholder="用户名"><br/><br/>
    头像1: <input type="file" name="face1"><br/><br/>
    头像2: <input type="file" name="face2"><br/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>
{{ end }}
  (3)、定义业务控制类
package admin

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"path"
)

type UserController struct {
}


// 添加:不同名字的多文件上传
func (con UserController) AddNotFileNameUpload(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/user/addnotfilenameupload.html", gin.H{
		"title": "添加不同名字的多文件上传",
	})
}

// 不同文件名的多文件上传
func (con UserController) DoNotFileNameUploads(c *gin.Context) {
	//获取表单中提交的username
	username := c.PostForm("username")
	//获取文件
	file1, err1 := c.FormFile("face1")
	file2, err2 := c.FormFile("face2")
	//判断上传文件上否存在
	if err1 != nil { //说明上传文件不存在
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": err1.Error(),
		})
		return
	}
	//判断上传文件上否存在
	if err2 != nil { //说明上传文件不存在
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": err2.Error(),
		})
		return
	}

	//设置需要上传的文件目录 file.Filename 获取文件名; "./static/upload" 是基于main.go文件路由的
	dst1 := path.Join("./static/upload", file1.Filename)
	//上传文件到指定目录
	c.SaveUploadedFile(file1, dst1)

	//设置需要上传的文件目录 file.Filename 获取文件名; "./static/upload" 是基于main.go文件路由的
	dst2 := path.Join("./static/upload", file2.Filename)
	//上传文件到指定目录
	c.SaveUploadedFile(file2, dst2)

	c.JSON(http.StatusOK, gin.H{
		"success":  "true",
		"username": username,
		"dst1":     dst1,
		"dst2":     dst2,
	})
}
  (4)、定义路由配置
package routers

import (
	"gin-mall/controllers/admin"
	"gin-mall/middlewares"
	"github.com/gin-gonic/gin"
)

// 设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
	//路由分组: 配置全局中间件:middlewares.InitMiddleware
	adminRouters := r.Group("/admin", middlewares.InitMiddleware)
	{

        // //不同名字的多文件上传
		adminRouters.GET("user/AddNotFileNameUpload", admin.UserController{}.AddNotFileNameUpload)
		//不同文件名的多文件上传
		adminRouters.POST("/user/DoNotFileNameUploads", admin.UserController{}.DoNotFileNameUploads)
	}
}
  (5)、主入口
package main

import (
	"gin-mall/routers"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("templates/**/**/*")//templates下有多少层目录就有多少个"/**"
	routers.AdminRoutersInit(r)
	r.Run(":8080")
}

  4、项目中实现多文件上传

https://gin-gonic.com/zh-cn/docs/examples/upload-file/multiple-file/ 

 (1)、项目结构

        跟第3点一样结构

 (2)、定义模板

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/user/addcommonfilenameupload.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{.title}}</title>
</head>
<body>
<h2>演示相同文件名的文件上传</h2>
<form action="/admin/user/doCommonFileNameUploads" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username" placeholder="用户名"><br/><br/>
    头像1: <input type="file" name="face[]"><br/><br/>
    头像2: <input type="file" name="face[]"><br/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>
{{ end }}

 (3)、定义业务控制类

package admin

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"path"
)

type UserController struct {
}


// 添加:相同名字的多文件上传
func (con UserController) AddCommonFileNameUpload(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/user/addcommonfilenameupload.html", gin.H{
		"title": "相同名字的多文件上传",
	})
}

// 相同文件名的多文件上传
func (con UserController) DoCommonFileNameUploads(c *gin.Context) {
	//获取表单中提交的username
	username := c.PostForm("username")
	//获取form
	form, _ := c.MultipartForm()
	//获取多文件
	files := form.File["face[]"]
	//遍历文件,并上传
	for _, file := range files {
		//设置需要上传的文件目录 file.Filename 获取文件名; "./static/upload" 是基于main.go文件路由的
		dst := path.Join("./static/upload", file.Filename)
		//上传文件到指定目录
		c.SaveUploadedFile(file, dst)
	}

	c.JSON(http.StatusOK, gin.H{
		"success":  "true",
		"username": username,
		"message":  "文件上传成功",
	})
}

 (4)、定义路由配置

package routers

import (
	"gin-mall/controllers/admin"
	"gin-mall/middlewares"
	"github.com/gin-gonic/gin"
)

// 设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
	//路由分组: 配置全局中间件:middlewares.InitMiddleware
	adminRouters := r.Group("/admin", middlewares.InitMiddleware)
	{

		//相同名字的多文件上传
		adminRouters.GET("/user/addcommonfilenameupload", admin.UserController{}.AddCommonFileNameUpload)
		//相同文件名的多文件上传
		adminRouters.POST("/user/doCommonFileNameUploads", admin.UserController{}.DoCommonFileNameUploads)
	}
}

 (5)、主入口

package main

import (
	"gin-mall/routers"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("templates/**/**/*")//templates下有多少层目录就有多少个"/**"
	routers.AdminRoutersInit(r)
	r.Run(":8080")
}

5、文件上传 按照日期存储

(1)、定义模板

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/user/add-by-date.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{.title}}</title>
</head>
<body>
<h2>演示文件按日期上传</h2>
<form action="/admin/user/DoUploadByDate" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username" placeholder="用户名"><br/><br/>
    头像: <input type="file" name="face"><br/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>
{{ end }}

(2)、定义业务控制类

package admin

import (
	"gin-mall/utils"
	"github.com/gin-gonic/gin"
	"net/http"
	"os"
	"path"
	"strconv"
)

type UserController struct {
}


// 添加:按日期单文件上传
func (con UserController) AddByDate(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/user/add-by-date.html", gin.H{
		"title": "添加:按日期单文件上传",
	})
}

//按日期单文件上传
/**
1.获取上传文件
2.获取后缀名,判断后缀是否正确: .jpg,.png,.gif,.jpeg
3.创建图片保存目录 ./static/upload/20230203
4.生成文件名称和文件保存目录
5.执行上传
*/
func (con UserController) DoUploadByDate(c *gin.Context) {
	//获取表单中提交的username
	username := c.PostForm("username")
	//1.获取上传文件
	file, err := c.FormFile("face")
	//判断上传文件上否存在
	if err != nil { //说明上传文件不存在
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": err.Error(),
		})
		return
	}
	//2.获取后缀名,判断后缀是否正确: .jpg,.png,.gif,.jpeg
	extName := path.Ext(file.Filename)
	//设置后缀map
	allowExtMap := map[string]bool{
		".jpg":  true,
		".png":  true,
		".gif":  true,
		".jpeg": true,
	}
	//判断后缀是否合法
	if _, ok := allowExtMap[extName]; !ok {
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": "上传文件后缀不合法",
		})
		return
	}
	//3.创建图片保存目录 ./static/upload/20230203
	//获取日期
	day := utils.GetDay()
	//拼接目录
	dir := "./static/upload/" + day
	//创建目录:MkdirAll 目录不存在,会一次性创建多层
	err = os.MkdirAll(dir, 0666)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": "fail",
			"message": "创建目录失败",
		})
		return
	}
	//4.生成文件名称和文件保存目录: models.GetUnix() 获取时间戳(int64); strconv.FormatInt() 把时间戳(int64)转换成字符串
	filename := strconv.FormatInt(utils.GetUnix(), 10) + extName
	//5.执行上传
	dst := path.Join(dir, filename)
	//上传文件到指定目录
	c.SaveUploadedFile(file, dst)
	c.JSON(http.StatusOK, gin.H{
		"success":  "true",
		"username": username,
		"dst":      dst,
	})
}

(3)、定义路由配置

package routers

import (
	"gin-mall/controllers/admin"
	"gin-mall/middlewares"
	"github.com/gin-gonic/gin"
)

// 设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
	//路由分组: 配置全局中间件:middlewares.InitMiddleware
	adminRouters := r.Group("/admin", middlewares.InitMiddleware)
	{

		//添加:按日期单文件上传
		adminRouters.GET("/user/AddByDate", admin.UserController{}.AddByDate)
		//添加:按日期单文件上传
		adminRouters.POST("/user/DoUploadByDate", admin.UserController{}.DoUploadByDate)
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 很高兴回答你的问题:Go 语言支持文件,你可以使用标准库中的 http 包中的 PostForm 函数来上文件。示例代码如下:resp, err := http.PostForm("http://example.com/upload", url.Values{"key": {"value"}, "file": {open("/path/to/file")}}) ### 回答2: go语言实现文件的代码可以使用gin框架来编写。 首先,我们需要导入gin框架的依赖包和其他必要的包: ```go import ( "github.com/gin-gonic/gin" "net/http" ) ``` 接下来,我们可以创建一个路由函数来处理文件的请求: ```go func uploadFile(c *gin.Context) { file, err := c.FormFile("file") // 获取文件信息 if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "文件失败", }) return } // 将文件保存到本地,可以根据需求修改存储路径 err = c.SaveUploadedFile(file, "./uploads/"+file.Filename) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "文件保存失败", }) return } c.JSON(http.StatusOK, gin.H{ "message": "文件成功", }) } ``` 然后,我们可以创建一个gin的路由器,并注册上文件的路由: ```go func main() { r := gin.Default() r.POST("/upload", uploadFile) // 注册上文件的路由 r.Run(":8080") // 启动服务 } ``` 最后,我们可以运行这个程序,并使用Postman或者其他工具发送一个POST请求,其中包含一个名为"file"的文件参数,即可实现文件的功能。 以上是用go语言实现文件的代码,希望能对你有帮助。 ### 回答3: go语言文件的代码如下: ```go package main import ( "fmt" "io" "log" "net/http" "os" ) func main() { http.HandleFunc("/upload", uploadFile) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } func uploadFile(w http.ResponseWriter, req *http.Request) { // 获取上文件 file, handler, err := req.FormFile("file") if err != nil { fmt.Println("Error Retrieving the File") fmt.Println(err) return } defer file.Close() // 创建保存文件的目录 os.MkdirAll("./uploads", os.ModePerm) // 创建并打开新的文件 dst, err := os.Create("./uploads/" + handler.Filename) if err != nil { fmt.Println(err) return } defer dst.Close() // 将上文件内容复制到新的文件 _, err = io.Copy(dst, file) if err != nil { fmt.Println(err) return } // 成功保存文件 fmt.Fprintf(w, "File uploaded successfully") } ``` 通过以上代码,可以实现一个简单的文件服务。在`main`函数中,创建路由规则`/upload`来处理文件请求。在`uploadFile`函数中,通过`req.FormFile("file")`获取上文件,然后创建保存文件的目录并打开新的文件,最后将上文件内容复制到新的文件中。如果上成功,返回`File uploaded successfully`,否则返回相应的错误信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值