iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang gin接收json数据和图像
  • 912
分享到

Golang gin接收json数据和图像

2024-02-09 12:02:04 912人浏览 独家记忆
摘要

PHP小编百草为您介绍golang gin框架中如何接收JSON数据和图像。在开发过程中,我们经常需要处理前端传递过来的jsON数据以及图像文件。Golang的gin框架提供了简单易用

PHP小编百草为您介绍golang gin框架中如何接收JSON数据和图像。在开发过程中,我们经常需要处理前端传递过来的jsON数据以及图像文件。Golang的gin框架提供了简单易用的方法来接收和处理这些数据。通过本文的介绍,您将了解到如何在gin框架中使用结构体来接收JSON数据,以及如何处理上传的图像文件。让我们一起来探索吧!

问题内容

我有请求处理程序的代码:

func (h *handlers) updateprofile() gin.handlerfunc {
    type request struct {
        username    string `json:"username" binding:"required,min=4,max=20"`
        description string `json:"description" binding:"required,max=100"`
    }

    return func(c *gin.context) {
        var updaterequest request

        if err := c.bindjson(&updaterequest); err != nil {
            var validationerrors validator.validationerrors

            if errors.as(err, &validationerrors) {
                validateerrors := base.bindingerror(validationerrors)
                c.abortwithstatusjson(http.statusbadrequest, gin.h{"error": validateerrors})
            } else {
                c.abortwitherror(http.statusbadrequest, err)
            }

            return
        }

        avatar, err := c.formfile("avatar")
        if err != nil {
            c.abortwithstatusjson(http.statusbadrequest, gin.h{
                "error": "image not contains in request",
            })
            return
        }

        log.print(avatar)

        if avatar.size > 3<<20 { // if avatar size more than 3mb
            c.abortwithstatusjson(Http.statusbadrequest, gin.h{
                "error": "image is too large",
            })
            return
        }

        file, err := avatar.open()
        if err != nil {
            c.abortwitherror(http.statusinternalservererror, err)
        }

        session := sessions.default(c)
        id := session.get("sessionid")
        log.printf("id type: %t", id)

        err = h.userservice.updateprofile(fmt.sprintf("%v", id), file, updaterequest.username, updaterequest.description)
        if err != nil {
            c.abortwithstatusjson(http.statusbadrequest, gin.h{})
            return
        }

        c.indentedjson(http.statusnocontent, gin.h{"message": "succesfull update"})
    }
}

我对此处理程序进行了单元测试

func testuser_updateprofile(t *testing.t) {
    type testcase struct {
        name               string
        image              io.reader
        username           string
        description        string
        expectedstatuscode int
    }

    router := gin.default()

    memstore := memstore.newstore([]byte("secret"))
    router.use(sessions.sessions("session", memstore))

    usergroup := router.group("user")
    repo := user.newmemory()
    service := userservice.new(repo)
    userhandlers.reGISter(usergroup, service)

    testimage := make([]byte, 100)
    rand.read(testimage)
    image := bytes.newreader(testimage)

    testcases := []testcase{
        {
            name:               "request with image",
            image:              image,
            username:           "bobik",
            description:        "wanna be sharik",
            expectedstatuscode: http.statusnocontent,
        },
        {
            name:               "request without image",
            image:              nil,
            username:           "sharik",
            description:        "wanna be bobik",
            expectedstatuscode: http.statusnocontent,
        },
    }

    for _, tc := range testcases {
        t.run(tc.name, func(t *testing.t) {
            body := &bytes.buffer{}
            writer := multipart.newwriter(body)

            imagewriter, err := writer.createfORMfile("avatar", "test_avatar.jpg")
            if err != nil {
                t.fatal(err)
            }

            if _, err := io.copy(imagewriter, image); err != nil {
                t.fatal(err)
            }

            data := map[string]interface{}{
                "username":    tc.username,
                "description": tc.description,
            }
            jsondata, err := json.marshal(data)
            if err != nil {
                t.fatal(err)
            }

            jsonwriter, err := writer.createformfield("json")
            if err != nil {
                t.fatal(err)
            }

            if _, err := jsonwriter.write(jsondata); err != nil {
                t.fatal(err)
            }

            writer.close()

            // creating request
            req := httptest.newrequest(
                http.methodpost,
                "http://localhost:8080/user/account/updateprofile",
                body,
            )
            req.header.set("content-type", writer.formdatacontenttype())
            log.print(req)

            w := httptest.newrecorder()
            router.servehttp(w, req)

            assert.equal(t, tc.expectedstatuscode, w.result().statuscode)
        })
    }
}

在测试过程中出现以下错误: 错误#01:数字文字中的无效字符“-”

这是请求正文(我用 log.print(req) 打印它):

&{POST http://localhost:8080/user/account/updateprofile HTTP/1.1 1 1 map[Content-Type:[multipart/form-data; boundary=30b24345de9d8d83ecbdd146262d86894c45b4f3485e4615553621fd2035]] {--30b24345de9d8d83ecbdd146262d86894c45b4f3485e4615553621fd2035
Content-Disposition: form-data; name="avatar"; filename="test_avatar.jpg"
Content-Type: application/octet-stream


--30b24345de9d8d83ecbdd146262d86894c45b4f3485e4615553621fd2035
Content-Disposition: form-data; name="json"

{"description":"wanna be bobik","username":"sharik"}
--30b24345de9d8d83ecbdd146262d86894c45b4f3485e4615553621fd2035--
}  414 [] false localhost:8080 map[] map[]  map[] 192.0.2.1:1234 http://localhost:8080/user/account/updateprofile    }

首先,我只有字符串作为 json 数据并将其转换为字节。当出现错误时,我使用 json.marshal 转换了 json 数据,但没有成功。我想用 c.bind 解析 json 数据并用 c.formfile 解析给定图像,这可能吗?

更新。我替换了代码先获取头像,然后通过bind结构获取json。现在我有 eof 错误。

解决方法

tl;dr

我们可以定义一个结构体来同时接收json数据和图像文件(注意字段标签):

var updaterequest struct {
    avatar *multipart.fileheader `form:"avatar" binding:"required"`
    user   struct {
        username    string `json:"username" binding:"required,min=4,max=20"`
        description string `json:"description" binding:"required,max=100"`
    } `form:"user" binding:"required"`
}

// c.shouldbind will choose binding.formmultipart based on the content-type header.
// we call c.shouldbindwith to make it explicitly.
if err := c.shouldbindwith(&updaterequest, binding.formmultipart); err != nil {
    _ = c.abortwitherror(http.statusbadrequest, err)
    return
}

gin可以自动解析multipart/form-data中的其他内容类型吗?

例如,xmlyaml

当前的 gin (@1.9.0) 不会自动解析 multipart/form-data 中的 xmlyamljson 很幸运,因为当目标字段是结构体或映射时,gin 恰好使用 json.unmarshal 解析表单字段值。请参阅 binding.setwithpropertype。

我们可以像这样自己解析它们(updaterequest.event 是表单中的字符串值):

var event struct {
    at     time.time `xml:"time" binding:"required"`
    player string    `xml:"player" binding:"required"`
    action string    `xml:"action" binding:"required"`
}

if err := binding.xml.bindbody([]byte(updaterequest.event), &event); err != nil {
    _ = c.abortwitherror(http.statusbadrequest, err)
    return
}

(请不要与 application/xml 请求中的 yamlapplication/x-yaml 请求中的 xml 混淆。仅当 xml 内容或 yaml 内容位于 中时才需要这样做多部分/表单-data 请求) .

其他

  1. c.bindjson 不能用于从 multipart/form-data 读取 json,因为它假定请求正文以有效的 json 开头。但它是从一个边界开始的,看起来像 --30b24345d...。这就是为什么它失败并显示错误消息 invalid character '-' in numeric literal
  2. c.formfile("avatar") 之后调用 c.bindjson 不起作用,因为调用 c.formfile 会使整个请求正文被读取。并且 c.bindjson 后面没有什么可读的。这就是您看到 eof 错误的原因。

单个可运行文件中的演示

这是完整的演示。使用 go test 运行 ./... -v -count 1:

package m

import (
    "bytes"
    "crypto/rand"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "net/http/httptest"
    "testing"
    "time"

    "GitHub.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "github.com/stretchr/testify/assert"
)

func handle(c *gin.Context) {
    var updateRequest struct {
        Avatar *multipart.FileHeader `form:"avatar" binding:"required"`
        User   struct {
            Username    string `json:"username" binding:"required,min=4,max=20"`
            Description string `json:"description" binding:"required,max=100"`
        } `form:"user" binding:"required"`
        Event string `form:"event" binding:"required"`
    }

    // c.ShouldBind will choose binding.FormMultipart based on the Content-Type header.
    // We call c.ShouldBindWith to make it explicitly.
    if err := c.ShouldBindWith(&updateRequest, binding.FormMultipart); err != nil {
        _ = c.AbortWithError(http.StatusBadRequest, err)
        return
    }
    fmt.Printf("%#v\n", updateRequest)

    var event struct {
        At     time.Time `xml:"time" binding:"required"`
        Player string    `xml:"player" binding:"required"`
        Action string    `xml:"action" binding:"required"`
    }

    if err := binding.XML.BindBody([]byte(updateRequest.Event), &event); err != nil {
        _ = c.AbortWithError(http.StatusBadRequest, err)
        return
    }

    fmt.Printf("%#v\n", event)
}

func TestMultipartForm(t *testing.T) {
    testImage := make([]byte, 100)

    if _, err := rand.Read(testImage); err != nil {
        t.Fatal(err)
    }
    image := bytes.NewReader(testImage)

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    imageWriter, err := writer.CreateFormFile("avatar", "test_avatar.jpg")
    if err != nil {
        t.Fatal(err)
    }

    if _, err := io.Copy(imageWriter, image); err != nil {
        t.Fatal(err)
    }

    if err := writer.WriteField("user", `{"username":"bobik","description":"wanna be sharik"}`); err != nil {
        t.Fatal(err)
    }

    xmlBody := `

   
   playerOne
   strike (miss)
`
    if err := writer.WriteField("event", xmlBody); err != nil {
        t.Fatal(err)
    }

    writer.Close()

    req := httptest.NewRequest(
        http.MethodPost,
        "http://localhost:8080/update",
        body,
    )
    req.Header.Set("Content-Type", writer.FormDataContentType())
    fmt.Printf("%v\n", req)

    w := httptest.NewRecorder()
    c, engine := gin.CreateTestContext(w)
    engine.POST("/update", handle)
    c.Request = req
    engine.HandleContext(c)

    assert.Equal(t, 200, w.Result().StatusCode)
}

感谢您的阅读!

以上就是Golang gin接收json数据和图像的详细内容,更多请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: Golang gin接收json数据和图像

本文链接: https://www.lsjlt.com/news/562547.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Golang gin接收json数据和图像
    php小编百草为您介绍Golang gin框架中如何接收JSON数据和图像。在开发过程中,我们经常需要处理前端传递过来的JSON数据以及图像文件。Golang的gin框架提供了简单易用...
    99+
    2024-02-09
  • java如何接收json数据
    Java可以通过使用第三方库(如Jackson、Gson等)来接收和解析JSON数据。以下是使用Jackson库来接收JSON数据的...
    99+
    2023-09-22
    java json
  • php如何接收json数据
    在PHP中,可以使用`file_get_contents`函数来接收JSON数据。以下是一个接收JSON数据并处理的示例代码:```...
    99+
    2023-08-29
    php json
  • AJAX中怎么接收JSON数据
    AJAX中怎么接收JSON数据,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、 JSON如何来表示对象的 2、 JSON如何来表示数组的 复...
    99+
    2024-04-02
  • Golang Gin解析JSON请求数据避免出现EOF错误
    目录环境1. 结论2. EOF错误复现3. ShouldBindBodyWith 源码分析JSON是前后端交互的重要数据类型之一,使用Gin Web框架可以很方便地将HTTP请求报文...
    99+
    2024-04-02
  • 如何接收ajax传的json数据
    要接收通过AJAX传递的JSON数据,需要使用服务器端的编程语言来处理和解析数据。下面是一个示例,使用PHP来接收AJAX传递的JS...
    99+
    2023-09-13
    ajax json
  • SpringBoot如何接收前端传来的json数据
    目录SpringBoot接收前端传来的json数据使用POJO使用Map接收使用POJO和Map接收的比较PO和VO相结合SpringBoot接收json入参总结SpringBoot...
    99+
    2023-05-14
    SpringBoot json数据 接收前端的json数据 SpringBoot接收前端数据
  • JAVA 接收JSON数据,并进行转换处理
    在日常业务中经常需要与外部系统交互处理数据,在此文章中记录一下我在项目中处理json数据流程。 第一种以实体类处理 以文档中的数据结构构建实体类,使字段与需要接收转换的JSON字段变量名尽量保持一致,如果不一致,则会获取不到变量的数值,也可...
    99+
    2023-09-05
    java json 开发语言
  • SpringBoot怎么接收前端传来的json数据
    本文小编为大家详细介绍“SpringBoot怎么接收前端传来的json数据”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot怎么接收前端传来的json数据”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-07-05
  • golang接收post和get请求参数处理
    目录1、golang中获取请求接口中数据(GET)方式一: API参数 ctx.Param(name string)或者ctx.Params.ByName(name string)方...
    99+
    2023-03-08
    golang post和get请求 golang post get
  • SpringMVC中的json数据怎么利用controller进行接收
    SpringMVC中的json数据怎么利用controller进行接收?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.jsp页面发送ajax的post请求:functio...
    99+
    2023-05-31
    springmvc controller json
  • 使用mybatisplus接收mysql字段为json类型的数据
    一.数据库设计 CREATE TABLE `inv_learning_examination_questions` ( `id` bigint(20) NOT NULL, `title` varchar(255) CHARA...
    99+
    2023-08-31
    sql 数据库
  • GoLang Socket.io 发送的数据无法在 React 中接收
    积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《GoLang Socket.io ...
    99+
    2024-04-04
  • CNTK怎么处理文本数据和图像数据
    CNTK(Microsoft Cognitive Toolkit)是一个深度学习框架,可以用来处理文本数据和图像数据。以下是CNTK...
    99+
    2024-04-02
  • Chainer怎么处理文本数据和图像数据
    Chainer可以处理文本数据和图像数据并进行相应的预处理操作。以下是Chainer处理文本数据和图像数据的一般步骤: 处理文本数据...
    99+
    2024-04-02
  • 如何使用ajax接收后台发送过来的json数据
    如何使用ajax接收后台发送过来的json数据?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。后台代码package com.sidan.outjson; ...
    99+
    2023-06-08
  • golang接收post和get请求参数如何处理
    这篇文章主要讲解了“golang接收post和get请求参数如何处理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang接收post和get请求参数如何处理”吧!1、golang中获取...
    99+
    2023-07-05
  • Flink支持的数据源和数据接收器有哪些
    Flink支持多种数据源和数据接收器,包括但不限于: 数据源: 文件系统(Filesystem):从本地文件系统或分布式文件系统如...
    99+
    2024-04-02
  • golang中怎么进行数据和json的相互转换
    一、什么是 JSON?JSON 全称为 JavaScript Object Notation,是一种轻量级的数据交换格式,其最大的特点是可读性很高。JSON 格式的数据易于阅读以及解析,也非常适合与服务器和客户端之间进行数据交换。二、gol...
    99+
    2023-05-14
  • golang中如何进行数据和json的相互转换
    这篇文章主要讲解了“golang中如何进行数据和json的相互转换”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang中如何进行数据和json的相互转换”吧!一、什么是 JSONJSO...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作