簡體   English   中英

如何在 go gin 中獲取從 JSON 發布的文件?

[英]How to get file posted from JSON in go gin?

我想保存由 JSON 發布的圖像文件。

這是帖子的結構:

type Article struct {
    Title   string `json:"title"`
    Body string `json:"body"`
    File    []byte `json:"file"`
}

處理程序是:

   func PostHandler(c *gin.Context) {
        var err error
        var json Article
        err = c.BindJSON(&json)
        if err != nil {
            log.Panic(err)
        }

    //handle photo upload
        var filename string
        file, header, err := json.File  //assignment count mismatch: 3 = 1

        if err != nil {
            fmt.Println(err)
            filename = ""

        } else {
            data, err := ioutil.ReadAll(file)
            if err != nil {
                fmt.Println(err)
                return
            }

            filename = path.Join("media", +shared.RandString(5)+path.Ext(header.Filename))

            err = ioutil.WriteFile(filename, data, 0777)
            if err != nil {
                io.WriteString(w, err.Error())
                return
            }

        }
...

但我明白了

分配計數不匹配:3 = 1

我從一個工作正常的多部分表單處理程序中復制了文件處理部分,但顯然,

file, header, err := r.FormFile("uploadfile")

不能翻譯成JSON處理。

我查看了 gin 文檔,但找不到涉及 json 文件處理的示例。 那么我該如何解決呢?

使用 Gin 獲取上傳的文件

我認為您的問題是“使用 Gin,如何獲取上傳的文件?”。 大多數開發人員不上傳使用 JSON 編碼的文件,這可以做到,但需要將文件作為 base64 字符串包含在內(並增加文件大小約 33%)。

常見(且更有效)的做法是使用“multipart/form-data”編碼上傳文件。 其他人提供的代碼file, header, err:= c.Request.FormFile("file")有效,但它劫持了 Gin 擴展的下划線“net/http”包。

我的建議是使用ShouldBind ,但您也可以使用 Gin 包提供的FormFileMultipartForm方法。

下面的例子。 Gin 頁面https://github.com/gin-gonic/gin#model-binding-and-validationhttps://github.com/gin-gonic/gin#上也提供了類似(但不太詳細)的解釋上傳文件


上傳一個文件


客戶

HTML

<form action="/upload" method="POST">
  <input type="file" name="file">
  <input type="submit">
</form>

卷曲

curl -X POST http://localhost:8080/upload \
  -F "file=../path-to-file/file.zip" \
  -H "Content-Type: multipart/form-data"

服務器

package main

import (
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
    "io/ioutil"
)

type Form struct {
    File *multipart.FileHeader `form:"file" binding:"required"`
}

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

    // Set a lower memory limit for multipart forms (default is 32 MiB)
    // router.MaxMultipartMemory = 8 << 20  // 8 MiB

    router.POST("/upload", func(c *gin.Context) {

        // Using `ShouldBind`
        // --------------------
        var form Form
        _ := c.ShouldBind(&form)

        // Get raw file bytes - no reader method
        // openedFile, _ := form.File.Open()
        // file, _ := ioutil.ReadAll(openedFile)

        // Upload to disk
        // `form.File` has io.reader method
        // c.SaveUploadedFile(form.File, path)
        // --------------------

        // Using `FormFile`
        // --------------------
        // formFile, _ := c.FormFile("file")

        // Get raw file bytes - no reader method
        // openedFile, _ := formFile.Open()
        // file, _ := ioutil.ReadAll(openedFile)

        // Upload to disk
        // `formFile` has io.reader method
        // c.SaveUploadedFile(formFile, path)
        // --------------------
        
        c.String(http.StatusOK, "Files uploaded")
    })

    // Listen and serve on 0.0.0.0:8080
    router.Run(":8080")
}

上傳多個文件


客戶

HTML

<form action="/upload" method="POST" multiple="multiple">
  <input type="file" name="files">
  <input type="submit">
</form>

卷曲

curl -X POST http://localhost:8080/upload \
  -F "files=../path-to-file/file1.zip" \
  -F "files=../path-to-file/file2.zip" \
  -H "Content-Type: multipart/form-data"

服務器

package main

import (
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
    "io/ioutil"
)

type Form struct {
    Files []*multipart.FileHeader `form:"files" binding:"required"`
}

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

    // Set a lower memory limit for multipart forms (default is 32 MiB)
    // router.MaxMultipartMemory = 8 << 20  // 8 MiB

    router.POST("/upload", func(c *gin.Context) {

        // Using `ShouldBind`
        // --------------------
        var form Form
        _ := c.ShouldBind(&form)

        // for _, formFile := range form.Files {

          // Get raw file bytes - no reader method
          // openedFile, _ := formFile.Open()
          // file, _ := ioutil.ReadAll(openedFile)

          // Upload to disk
          // `formFile` has io.reader method
          // c.SaveUploadedFile(formFile, path)

        // }
        // --------------------

        // Using `MultipartForm`
        // --------------------
        // form, _ := c.MultipartForm()
        // formFiles, _ := form["files[]"]

        // for _, formFile := range formFiles {

          // Get raw file bytes - no reader method
          // openedFile, _ := formFile.Open()
          // file, _ := ioutil.ReadAll(openedFile)

          // Upload to disk
          // `formFile` has io.reader method
          // c.SaveUploadedFile(formFile, path)

        // }
        // --------------------
        
        c.String(http.StatusOK, "Files uploaded")
    })

    // Listen and serve on 0.0.0.0:8080
    router.Run(":8080")
}

在您的代碼中,您說var json Article類型文章定義為

type Article struct {
    Title   string `json:"title"`
    Body string `json:"body"`
    File    []byte `json:"file"`
}

File 是[]byte類型。 類型 byte 除了它所持有的內容外不返回任何東西

您的Article.Filer.FormFile ,其中FormFile是返回 3 個項目的方法

所以file, header, err:= json.File不是file, header, err:= r.FormFile("foo")

請參閱 godocs ->此處的實現和方法描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM