我试图从 struct 数组中读取文件,但无法读取.postman 来了.

以下是我的代码:

type MasterTemplate struct {
    ID       uuid.UUID `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"`
    FilePath string    `form:"file_path" json:"file_path"`
    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"`
    } `form:"content" json:"content"`
    UserID uuid.UUID `form:"user_id" json:"user_id"`
}

func (tmplController *MessageTemplateController) CreateMsgTemplateController(ctx *gin.Context) {
    userID := ctx.Param("user_id")

    userUUID, err := uuid.Parse(userID)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        ctx.Abort()
        return
    }

    if ctx.Request.ContentLength == 0 {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": "Invalid/Empty body request",
        })
        ctx.Abort()
        return
    }

    err = ctx.Request.ParseMultipartForm(10 * 1024 * 1024)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        return
    }

    var msgTemplate *models.MasterTemplate

    if err := ctx.ShouldBind(&msgTemplate); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "Gin Error": err.Error(),
        })
        return
    }

    config, err := config.LoadConfig("credentials")
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "rerror": err.Error(),
        })
        return
    }

    
    for _, sms := range msgTemplate.Content {

        lanaguageID, err := uuid.Parse(sms.MsgTmplateLangId)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "rerror": err.Error(),
            })
            return
        }

        templateContent := models.MessageTemplateContenet{
            ID:                uuid.New(),
            LanguageID:        lanaguageID,
            IsSms:             true,
            IsVoice:           false,
            FilePath:          "",
            Content:           sms.SMSContent,
            UserID:            userUUID,
            // MessageTemplateID: data.ID,
            IsDeleted:         false,
        }

        _, err = tmplController.contents.CreateMessageTemplateContent(&templateContent, ctx)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "rerror": err.Error(),
            })
            return
        }
    }

    msgTemplate.IsVoice = true
    msgTemplate.IsSms = false

    msgTemplate.IsSms = false
    msgTemplate.IsVoice = true

    for x, voice := range msgTemplate.Content {
        fmt.Println(voice.MsgTmplateLangId)
        fmt.Println(x)
        fileHeader, err := ctx.FormFile(fmt.Sprintf("content[%c][file]", x))
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": err.Error(),
            })
            return
        }
        file, err := voice.File.Open()
        if err != nil {
            ctx.JSON(400, gin.H{"error": "Failed to open uploaded file"})
            return
        }
        defer file.Close()
        fmt.Println(file)

        if !utilities.IsValidFile(fileHeader) {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": "Invalid file format. Only .mp3 and .wav files are allowed.",
            })
            return
        }
        if fileHeader.Size > 3*1024*1024 {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": "File size exceeds the limit. Maximum file size is 3MB.",
            })
            return
        }
        audioPath := uuid.New().String() + fileHeader.Filename
        uploadPath := filepath.Join("./msgtemplate", audioPath)
        // Save the uploaded file
        if err := ctx.SaveUploadedFile(fileHeader, uploadPath); err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": err.Error(),
            })
            return
        }
        session, err := awsservice.S3BucketSessionHandler()
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": err.Error(),
            })
            return
        }
        fileURL, err := awsservice.UploadFiles(session, uploadPath, config.AWS_AUDIO_BUCKET)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "error": err.Error(),
            })
            return
        }
        lanaguageID, err := uuid.Parse(voice.MsgTmplateLangId)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "rerror": err.Error(),
            })
            return
        }
        templateContent := models.MessageTemplateContenet{
            ID:         uuid.New(),
            LanguageID: lanaguageID,
            IsSms:      false,
            IsVoice:    true,
            IsDeleted:  false,
            FilePath:   uploadPath,
            Content:    *fileURL,
            UserID:     userUUID,
            // MessageTemplateID: data.ID,
        }

        _, err = tmplController.contents.CreateMessageTemplateContent(&templateContent, ctx)
        if err != nil {
            ctx.JSON(http.StatusBadRequest, gin.H{
                "rerror": err.Error(),
            })
            return
        }

    }
}

推荐答案

postman request Below is the refactored code:

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
    }

    // We get the user ID from the route the we convert it to UUID 
    // We convert to UUID since that is the input type
    userUUID, err := uuid.Parse(ctx.Param("user_id"))
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
        })
        return
    }

    // We get the other parameters in the struct
    msgTemplate := models.MasterTemplate{
        ID:      ctx.Request.Form.Get("id"),
        Title:   ctx.Request.Form.Get("title"),
        IsSms:   ctx.Request.Form.Get("is_sms") == "true",
        IsVoice: ctx.Request.Form.Get("is_voice") == "true",
        UserID:  userUUID,
    }


    msgTemplate.Content = make([]models.Content, 0)
    for i := 0; ; i++ {
        fileInputName := fmt.Sprintf("content[%d][file]", i)
        if file, err := ctx.FormFile(fileInputName); err == nil {
            contentPrefix := fmt.Sprintf("content[%d]", i)
            msgTemplateLangIDKey := fmt.Sprintf("%s[msg_template_lang_id]", contentPrefix)
            smsContentKey := fmt.Sprintf("%s[sms_content]", contentPrefix)

            var fc models.Content
            fc.File = file
            fc.SMSContent = ctx.Request.Form.Get(smsContentKey)
            fc.MsgTmplateLangId = ctx.Request.Form.Get(msgTemplateLangIDKey)

            msgTemplate.Content = append(msgTemplate.Content, fc)
        } else {
            break
        }
    }

    // Now we can loop through the content to do what we want to now

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

Go相关问答推荐

Google OAuth2没有刷新令牌

如何创建两个连接的io.ReadWriteClosers以用于测试目的

Go -SDP服务器读缓冲区不会更改任何内容

Go:嵌入类型不能是类型参数""

如何在另一个文件夹中使用Delve运行二进制文件?

你能把用户界面文件中的GTK4应用程序窗口添加到GTK4应用程序中吗?

Websocket服务器实现与x/net库trowing 403

使用Go使用Gorm使用外键对数据进行排序

golang testscript .txtar 语法,用于 stderr 或 stdout 中包含的文本

htmx 表单 + gin 无法正确读取请求正文

Go struct 匿名字段是公开的还是私有的?

尽管存在 WaitGroup,Goroutines 似乎被打断了

Golang:如何判断通过缓冲通道进行通信时生产者或消费者是否较慢?

Go cmp - 如何为以 struct 为键的映射定义自定义相等性?

使用 package`regexp` 查找 Golang 中的所有 mactch 子字符串,但得到意外结果

Go 加密库创建的 PKCS1 公钥与openssl rsa ...之间的区别

Terraform 自定义提供程序 - 数据源架构

Dynamodb.ScanInput - 不能使用expr.Names()(类型 map[string]*string)作为类型 map[string]string

try 执行`go test ./... -v`时,Golang中有没有办法设置标志

如何使用 httputil.ReverseProxy 设置 X-Forwarded-For