我创建了一个示例来演示它应该如何工作。首先,让我展示代码,然后,我将向您介绍所有相关部分。
上传
上传在handlers_test.go 文件中完成。我编写了两个测试来展示如何使用多部分主体创建有效的 HTTP 请求(我假设通信是基于 HTTP 的)。在这里你可以找到代码:
package multipart
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHandleFile(t *testing.T) {
t.Run("MultipartRequest", func(t *testing.T) {
// instantiate multipart request
var buf bytes.Buffer
multipartWriter := multipart.NewWriter(&buf)
defer multipartWriter.Close()
// add form field
filePart, _ := multipartWriter.CreateFormFile("file", "file.txt")
filePart.Write([]byte("Hello, World!"))
r := httptest.NewRequest(http.MethodPost, "/file", &buf)
w := httptest.NewRecorder()
r.Header.Set("Content-Type", multipartWriter.FormDataContentType())
HandleFile(w, r)
data, _ := io.ReadAll(w.Result().Body)
assert.Equal(t, http.StatusOK, w.Result().StatusCode)
assert.Equal(t, []byte("Hello, World!"), data)
})
t.Run("PlainRequest", func(t *testing.T) {
r := httptest.NewRequest(http.MethodPost, "/file", nil)
w := httptest.NewRecorder()
HandleFile(w, r)
assert.Equal(t, http.StatusBadRequest, w.Result().StatusCode)
})
}
我们可以关注子测试MultipartRequest。首先,它实例化一个多部分主体,稍后将用作我们要发送的 HTTP 请求的请求负载。然后,我们创建一个文件部分并向其中写入虚拟内容。在发出请求之前,我们必须查看将用于解析内容的 Content-Type 标头。测试的其余部分应该非常简单。
读
读取(或解析)由 HTTP 服务器完成。涉及的文件是handlers.go文件:
package multipart
import (
"io"
"mime"
"mime/multipart"
"net/http"
"strings"
)
func HandleFile(w http.ResponseWriter, r *http.Request) {
mediaType, params, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
if strings.HasPrefix(mediaType, "multipart/") {
multipartReader := multipart.NewReader(r.Body, params["boundary"])
filePart, _ := multipartReader.NextPart()
// pay attention here when you read large file
data, _ := io.ReadAll(filePart)
w.Write(data)
return
}
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("request is not multipart"))
}
在这里,相关步骤可以总结在以下列表中:
- 我们从 HTTP 请求中检索并解析
Content-Type 标头
- 我们检查上面的值是否以字符串
multipart/开头
- 如果是这样,我们读取正文的下一部分(也是唯一的)并将其内容写入响应流
- 如果不是,我们向 HTTP 客户端返回一个
BadRequest错误
在代码中我放了一些cmets来解释一些值得关注的微妙部分。此外,我通过不处理任何可能发生的错误来简化代码库。
希望能帮助解决您的问题,让我知道!