Golang中如何读取数组结构体中的multipart.Fileheader

Golang中如何读取数组结构体中的multipart.Fileheader

type MasterTemplate struct {
	ID      string `form:"id" json:"id"`
	IsVoice bool   `form:"is_voice" json:"is_voice"`
	Title   string `form:"title" json:"title"`
	IsSms   bool   `form:"is_sms" json:"is_sms"`
	Content []struct {
		File             *multipart.FileHeader `form:"file" json:"file"`
		MsgTmplateLangId string                `form:"msg_template_lang_id" json:"msg_template_lang_id"`
		SMSContent       string                `form:"sms_content" json:"sms_content"`
		MsgContentID     string                `form:"msg_content_id" json:"msg_content_id"`
		FilePath         string                `form:"file_path" json:"file_path"`
	} `form:"content" json:"content"`
	UserID uuid.UUID `form:"user_id" json:"user_id"`
}
func (tmplController *MessageTemplateController) CreateMsgTemplateController(ctx *gin.Context) {

	// var msgTemplate models.MasterTemplate
	err := ctx.Request.ParseMultipartForm(10 * 1024 * 1024)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"error": err.Error(),
		})
		return
	}
	var contents []models.MasterTemplate

	form := ctx.Request.MultipartForm
	files := form.File["content[file]"]
	// formFileds := form.Value
	// formFields := ctx.Request.MultipartForm.Value

	for x, file := range files {

		var msgTemplate models.MasterTemplate

		msgTemplate.Content = make([]struct {
			File             *multipart.FileHeader `form:"file" json:"file"`
			MsgTmplateLangId string                `form:"msg_template_lang_id" json:"msg_template_lang_id"`
			SMSContent       string                `form:"sms_content" json:"sms_content"`
			MsgContentID     string                `form:"msg_content_id" json:"msg_content_id"`
			FilePath         string                `form:"file_path" json:"file_path"`
		}, len(files))

		// Bind the form data to the struct

		// Set the file data for this content item
		msgTemplate.Content[x].File = file
		contents = append(contents, msgTemplate)

	}

	ctx.JSON(http.StatusOK, gin.H{
		"response": contents,
	})
}

我如何获取文件及其关联信息。附件是我的 Postman 请求截图:

image


更多关于Golang中如何读取数组结构体中的multipart.Fileheader的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中如何读取数组结构体中的multipart.Fileheader的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中读取数组结构体中的multipart.FileHeader,需要使用正确的表单字段绑定方式。你的代码存在几个问题:每次循环都重新初始化Content切片,且没有绑定其他表单字段。以下是修正后的实现:

func (tmplController *MessageTemplateController) CreateMsgTemplateController(ctx *gin.Context) {
    // 首先解析multipart表单
    err := ctx.Request.ParseMultipartForm(10 * 1024 * 1024)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        return
    }
    
    // 使用gin的ShouldBind来绑定结构体
    var masterTemplate models.MasterTemplate
    if err := ctx.ShouldBind(&masterTemplate); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        return
    }
    
    // 获取文件数组
    form := ctx.Request.MultipartForm
    files := form.File["content[][file]"] // 注意数组格式
    
    // 将文件绑定到对应的Content项
    for i, file := range files {
        if i < len(masterTemplate.Content) {
            masterTemplate.Content[i].File = file
        }
    }
    
    // 处理文件保存等操作
    for i, content := range masterTemplate.Content {
        if content.File != nil {
            // 保存文件到服务器
            dst := "./uploads/" + content.File.Filename
            if err := ctx.SaveUploadedFile(content.File, dst); err != nil {
                ctx.JSON(http.StatusInternalServerError, gin.H{
                    "error": "Failed to save file: " + err.Error(),
                })
                return
            }
            // 更新文件路径
            masterTemplate.Content[i].FilePath = dst
        }
    }
    
    ctx.JSON(http.StatusOK, gin.H{
        "response": masterTemplate,
    })
}

如果需要手动处理表单字段,可以使用以下方式:

func (tmplController *MessageTemplateController) CreateMsgTemplateController(ctx *gin.Context) {
    err := ctx.Request.ParseMultipartForm(10 * 1024 * 1024)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        return
    }
    
    form := ctx.Request.MultipartForm
    var masterTemplate models.MasterTemplate
    
    // 获取普通字段
    masterTemplate.ID = form.Value["id"][0]
    masterTemplate.Title = form.Value["title"][0]
    masterTemplate.IsVoice = form.Value["is_voice"][0] == "true"
    masterTemplate.IsSms = form.Value["is_sms"][0] == "true"
    
    // 获取数组字段
    msgTemplateLangIds := form.Value["content[][msg_template_lang_id]"]
    smsContents := form.Value["content[][sms_content]"]
    msgContentIDs := form.Value["content[][msg_content_id]"]
    
    // 获取文件
    files := form.File["content[][file]"]
    
    // 构建Content数组
    maxLen := len(files)
    if len(msgTemplateLangIds) > maxLen {
        maxLen = len(msgTemplateLangIds)
    }
    
    masterTemplate.Content = make([]struct {
        File             *multipart.FileHeader `form:"file" json:"file"`
        MsgTmplateLangId string                `form:"msg_template_lang_id" json:"msg_template_lang_id"`
        SMSContent       string                `form:"sms_content" json:"sms_content"`
        MsgContentID     string                `form:"msg_content_id" json:"msg_content_id"`
        FilePath         string                `form:"file_path" json:"file_path"`
    }, maxLen)
    
    for i := 0; i < maxLen; i++ {
        if i < len(files) {
            masterTemplate.Content[i].File = files[i]
        }
        if i < len(msgTemplateLangIds) {
            masterTemplate.Content[i].MsgTmplateLangId = msgTemplateLangIds[i]
        }
        if i < len(smsContents) {
            masterTemplate.Content[i].SMSContent = smsContents[i]
        }
        if i < len(msgContentIDs) {
            masterTemplate.Content[i].MsgContentID = msgContentIDs[i]
        }
    }
    
    ctx.JSON(http.StatusOK, gin.H{
        "response": masterTemplate,
    })
}

Postman请求应该使用以下格式:

  • content[0][file]: 文件
  • content[0][msg_template_lang_id]: 值
  • content[1][file]: 文件
  • content[1][msg_template_lang_id]: 值
  • 以此类推…

或者使用数组格式:

  • content[][file]: 文件
  • content[][msg_template_lang_id]: 值
  • 多个文件和多组字段会自动匹配顺序
回到顶部