files字段上传多张图片问题?

 

html 页面

{{define "admin/register/index.html"}}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>admin/register/index.html</title>
</head>
<body>
    <form action="/admin/register/edit" method="post" enctype="multipart/form-data">

        用户名:<input type="text" name="username" id="username">

        <br>
        
        头像: <input type="file" name="files" id="files" multiple> 
 
        <input type="submit" value="提交">
    </form>
</body>
</html>


{{end}}

路由文件:adminRouters.go

package routers

import (
	"project/controllers/admins"

	"github.com/gin-gonic/gin"
)

func AdminRoutersInit(r *gin.Engine) {
	adminRouter := r.Group("/admin")
	{
		//
		adminRouter.GET("/", admins.AdminControllers{}.Index)

		// 登录
		adminRouter.GET("/index", admins.AdminControllers{}.PageIndex)
		adminRouter.POST("/login", admins.AdminControllers{}.Login)

		// 注册页面  上传多文件 multiple
		adminRouter.GET("/register", admins.AdminControllers{}.Register)
		adminRouter.POST("/register/edit", admins.AdminControllers{}.Edit)

		// 展示页面
		adminRouter.GET("/views", admins.AdminControllers{}.Views)

	}
}

controllers 控制器代码 adminControllers.go:

package admins

import (
	"fmt"
	"net/http"
	"os"
	"path"
	"project/models"
	"strconv"

	"github.com/gin-gonic/gin"
)

type AdminControllers struct{}

func (con AdminControllers) Index(c *gin.Context) {
	c.String(200, "admin后管项目")
}

func (con AdminControllers) PageIndex(c *gin.Context) {
	c.HTML(200, "admin/login/index.html", gin.H{
		"title": "admin后管项目",
	})
}

func (con AdminControllers) Login(c *gin.Context) {

	username := c.PostForm("username")
	password := c.PostForm("password")

	c.String(200, "用户名:=%v,密码:=%v \n", username, password)

	// c.HTML(200, "admin/views/index.html", gin.H{
	// 	"title": "viewAdmin页面",
	// })

}

func (con AdminControllers) Register(c *gin.Context) {
	c.HTML(200, "admin/register/index.html", gin.H{
		"title": "注册页面",
	})
}

func (con AdminControllers) Edit(c *gin.Context) {

	username := c.PostForm("username")

	fmt.Printf("username==%v \n", username)

	//1. html 页面有   multiple属性时候   头像: <input type="file" name="files" id="files" multiple>   通过 multipartform 获取上传文件form,         
     err := c.MultipartForm()
     if err != nil {
	 	c.String(http.StatusBadRequest, "get form err: %s", err.Error())
	 	return
	 }
	 files := form.File["files"]
	 // 当前时间获取
	 for _, file := range files {
	 	// fmt.Println("==========path=%v \n", file.Filename)
	 	filename := filepath.Base(file.Filename)
	 	// fmt.Println("===========%v \n", filename)
 	    dst := path.Join("./static/upload", filename)
	 	if err := c.SaveUploadedFile(file, dst); err != nil {
	 		c.String(http.StatusBadRequest, "upload file err: %s", err.Error())
	 		return
	 	}
	}

}

以上就是关于多文件上传 通过 multiple属性 input标签实现 多文件上传的代码部分。

另外补充一个关于存储文件在本地服务器时候,大量图片或者文件,我们需要区分后再存储,分组存储便于后续查询文件;这里我们可以给文件分组按照日期格式* 时间戳格式的进行存储。

这里对于代码部分改动一下:

package admins

import (
	"fmt"
	"net/http"
	"os"
	"path"
	"project/models"
	"strconv"

	"github.com/gin-gonic/gin"
)

type AdminControllers struct{}

func (con AdminControllers) Index(c *gin.Context) {
	c.String(200, "admin后管项目")
}

func (con AdminControllers) PageIndex(c *gin.Context) {
	c.HTML(200, "admin/login/index.html", gin.H{
		"title": "admin后管项目",
	})
}

func (con AdminControllers) Login(c *gin.Context) {

	username := c.PostForm("username")
	password := c.PostForm("password")

	c.String(200, "用户名:=%v,密码:=%v \n", username, password)

	// c.HTML(200, "admin/views/index.html", gin.H{
	// 	"title": "viewAdmin页面",
	// })

}

func (con AdminControllers) Register(c *gin.Context) {
	c.HTML(200, "admin/register/index.html", gin.H{
		"title": "注册页面",
	})
}

func (con AdminControllers) Edit(c *gin.Context) {

	username := c.PostForm("username")

	fmt.Printf("username==%v \n", username)

	//1. 获取上传文件
	file, err := c.FormFile("file")

	if err == nil {
		// 2. 获取文件后缀,判断是否类型正确 .png,.jpg,.gif,.jpeg,.png

		extName := path.Ext(file.Filename)

		allowExtMap := map[string]bool{
			".jpg":  true,
			".gif":  true,
			".png":  true,
			".jpeg": true,
		}

		if _, ok := allowExtMap[extName]; !ok {
			// c.Redirect() // 也可以跳转
			c.String(200, "上传的文件类型不合法")
			return
		}

		// 创建图片保存目录 、static/upload/20230630
		dayNum := models.GetDay()

		dir := path.Join("./static/upload", dayNum)

		err := os.MkdirAll(dir, 0666)
		if err != nil {
			fmt.Println(err)
			c.String(200, "MkdirAll失败")
			return
		}
		// 生成文件名称 和 文件保存的 目录
		// unix := models.GetUnix()
		// // unix + extName = filename
		// filename := strconv.FormatInt(unix, 10) + extName
		// 合并成一句
		filename := strconv.FormatInt(models.GetUnix(), 10) + extName

		// 执行上传
		dst := path.Join(dir, filename)
		c.SaveUploadedFile(file, dst)
	}


}

func (con AdminControllers) Views(c *gin.Context) {

	c.SetCookie("username", "王二妹", 3600, "/", "localhost", false, true)

	// c.String(200, "Views页面")
	c.HTML(http.StatusOK, "admin/views/index.html", gin.H{
		"title": "views页面",
	})
}

c.FormFile("file") 是在gin框架中用于获取单个文件上传的方法。它接收一个参数作为文件上传的表单字段名,并返回一个 *multipart.FileHeader 对象和一个可能的错误。

func uploadFile(c *gin.Context) {
    // 获取上传的文件
    file, err := c.FormFile("file")
    if err != nil {
        // 错误处理逻辑
    }

    // 处理文件
    // 保存文件到指定的路径
    err = c.SaveUploadedFile(file, "上传目录/"+file.Filename)
    if err != nil {
        // 错误处理逻辑
    }

    // 其他逻辑
}

在这个例子中,c.FormFile("file") 将根据表单字段名 "file" 获取上传的文件。如果文件不存在或出现错误,将返回相应的错误。

然后,你可以按照实际需求对文件进行进一步的处理,比如保存到指定路径。

需要注意的是,这个方法只能获取到单个文件上传的情况。如果需要处理多个同名文件上传,可以使用前面提到的 c.Request.MultipartForm.File 的方式进行处理。这里不过多阐述关于多文件还是单文件的上传问题了(如果有问题,可以留言)。

关于ctx.setCookie() 的使用……

在Gin框架中,使用ctx.SetCookie()方法来设置Cookie。下面是一个具体的实现示例:

func setCookie(c *gin.Context) {
    // 设置Cookie的参数和值
    c.SetCookie("my_cookie", "example value", 3600, "/", "localhost", false, true)
    
    // 其他逻辑
}

在这个例子中,我们使用c.SetCookie()方法来设置Cookie。方法接收的参数如下:

  • 第一个参数是Cookie的名称。
  • 第二个参数是Cookie的值。
  • 第三个参数是Cookie的过期时间(以秒为单位)。在这个例子中,设置Cookie的过期时间为3600秒(即1小时)。
  • 第四个参数是Cookie的路径,指定Cookie可用的路径。在这个例子中,我们将其设置为根路径 “/”。
  • 第五个参数是Cookie的域,指定Cookie可用的域名。在这个例子中,我们将其设置为 “localhost”,表示只能在本地测试环境使用。
  • 第六个参数是一个布尔值,指示是否使用HTTPS发送Cookie。在这个例子中,我们将其设置为false。
  • 第七个参数是一个布尔值,指示是否启用SameSite属性。在这个例子中,我们将其设置为true。

通过这样设置,即可在响应中将Cookie发送给客户端,客户端会自动存储并在后续的请求中发送回服务器。

func (con AdminControllers) Views(c *gin.Context) {

	c.SetCookie("username", "王二妹", 3600, "/", "localhost", false, true)

	// c.String(200, "Views页面")
	c.HTML(http.StatusOK, "admin/views/index.html", gin.H{
		"title": "views页面",
	})
}

方法接收的参数如下:

第一个参数是Cookie的名称。
第二个参数是Cookie的值。
第三个参数是Cookie的过期时间(以秒为单位)。在这个例子中,设置Cookie的过期时间为3600秒(即1小时)。
第四个参数是Cookie的路径,指定Cookie可用的路径。在这个例子中,我们将其设置为根路径 “/”。
第五个参数是Cookie的域,指定Cookie可用的域名。在这个例子中,我们将其设置为 “localhost”,表示只能在本地测试环境使用。
第六个参数是一个布尔值,指示是否使用HTTPS发送Cookie。在这个例子中,我们将其设置为false。
第七个参数是一个布尔值,指示是否启用SameSite属性。在这个例子中,我们将其设置为true。

需要注意的是,这只是一个简单的示例。在实际应用中,你可能需要根据需要进行更详细的设置,例如设置Cookie的过期时间、域名、Secure标记等。另外,Gin框架还提供了c.SetSameSite()方法,用于设置SameSite属性以及c.SetCookieOptions()用于更详细地设置Cookie的属性。

关于Cookie的过期时间补充一下:

设置的时间 Time seconds 值整数 大于0:代表 过期时间秒的到期后,自动过期,被浏览器清理。

设置的时间 Time seconds 值整数 小于0:代表过期了,同时也可以作为删除 delete cookie的程序。

 

希望本文对于你的学习有帮助!

Logo

欢迎加入我们的广州开发者社区,与优秀的开发者共同成长!

更多推荐