go http 服务器标头 Content-type 设置为 multipart/form-data,但在客户端获取 Content-Type: text/plain

go http server header Content-type set to multipart/form-data but get Content-Type: text/plain at the client

提问人:Jerome 提问时间:11/9/2023 更新时间:11/9/2023 访问量:44

问:

go 服务器将标头 Content-type 设置为 multipart/form-data

router.HandleFunc("/certificates", serveFilesHandler).Methods("GET")

func serveFilesHandler(w http.ResponseWriter, r *http.Request) {

    currentDir, err := os.Getwd()
    if err != nil {
        log.Fatal("Can not find the current directory: ", err)
    }
    pathToCertifs := "../certificates"

    // Create a multipart writer for the response
    multipartWriter := multipart.NewWriter(w)

    files := []string{"client.key", "server.key", "rootCA.key"}

    for _, filename := range files {
        filePath := filepath.Join(currentDir, pathToCertifs, filename)

        fmt.Println("see the filePath: ", filePath)

        // Open the file
        file, err := os.Open(filePath)
        if err != nil {}
        defer file.Close()

        // Create a new form file part
        part, err := multipartWriter.CreateFormFile("files", filename)
        if err != nil {}

        // Copy the file content to the part
        _, err = io.Copy(part, file)
        if err != nil {}
    }

    // Set the content type for the response
    w.Header().Set("Content-Type", multipartWriter.FormDataContentType())
    fmt.Println("Content-Type set to:", w.Header().Get("Content-Type"))
    // printout Content-Type set to: multipart/form-data; boundary=7b326

    // Close the multipart writer
    multipartWriter.Close()
}

但在客户端,我得到了

Expected multipart response, but received: text/plain; charset=utf-8

但是,有效载荷在体内

body, err := ioutil.ReadAll(resp.Body)
    if err != nil {}
Content-Type: text/plain; charset=utf-8
Response Body:
--aee406774ba6a054d52e39a3cdb72f42d32bd30828adbfb1982d278cab56
Content-Disposition: form-data; name="files"; filename="client.key"
Content-Type: application/octet-stream

-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNg4ZaTLC/GdLK
xzFDIyPlYyKs/hUXpPkZAQk+3gnvmBaDuMNq2jd2nQoQohmk1zIuD8oj9se5L+3P

但我无法按部分获取它,因为 Content-type 不是 multipart/form-data,所以这不起作用

multipartReader := multipart.NewReader(resp.Body, boundaryFromContentType(contentType))

    // Read each part
    for {
        part, err := multipartReader.NextPart()
        if err != nil {
            break
        }
        defer part.Close()
......

我错过了什么,谢谢?

ps:问更多细节来发布这个问题,我觉得很清楚,所以我添加了这一行,之后可能会起作用。

转到 http-headers

评论


答:

3赞 icza 11/9/2023 #1

在将任何内容写入响应正文之前,必须设置 HTTP 响应标头。提交标头后(在向响应正文写入内容时),无法设置或更改标头。

创建多部分编写器以及所有部分和内容,然后设置响应标头,然后仅关闭多部分编写器。关闭只是为了完成多部分消息并写入尾随边界,但其许多内容可能已经写入并提交。

在向多部分编写器添加/写入任何内容之前移动设置标头:

// Create a multipart writer for the response
multipartWriter := multipart.NewWriter(w)

w.Header().Set("Content-Type", multipartWriter.FormDataContentType())

// Now proceed to add files...