Хорошо, я наконец понял, как работает multipart.Reader
, и я нашел решение.
Сначала давайте выясним, что отличается от того, как обычно работает Гоа (отображение «автоматически» параметров запросов с помощью Payload
поля), с MultipartRequest()
, я должен сделать отображение самостоятельно, поэтому Payload
может фактически иметь любую структуру.
В моем случае, я переопределил мою Payload
структуруследующим образом:
// ImageUpload single image upload element
var ImageUpload = Type("ImageUpload", func() {
Description("A single Image Upload type")
Attribute("type", String)
Attribute("bytes", Bytes)
Attribute("name", String)
})
// ImageUploadPayload is a list of files
var ImageUploadPayload = Type("ImageUploadPayload", func() {
Description("Image Upload Payload")
Attribute("Files", ArrayOf(ImageUpload), "Collection of uploaded files")
})
В двух словах, я хочу поддержать загрузку нескольких файлов, каждый со своим mime-типом, именем файла и данными.
Чтобы добиться этого, я реализовал multipart.go
функция декодера, как это:
func ImagesUploadDecoderFunc(mr *multipart.Reader, p **images.ImageUploadPayload) error {
res := images.ImageUploadPayload{}
for {
p, err := mr.NextPart()
if err == io.EOF {
break
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
return err
}
_, params, err := mime.ParseMediaType(p.Header.Get("Content-Disposition"))
if err != nil {
// can't process this entry, it probably isn't an image
continue
}
disposition, _, err := mime.ParseMediaType(p.Header.Get("Content-Type"))
// the disposition can be, for example 'image/jpeg' or 'video/mp4'
// I want to support only image files!
if err != nil || !strings.HasPrefix(disposition, "image/") {
// can't process this entry, it probably isn't an image
continue
}
if params["name"] == "file" {
bytes, err := ioutil.ReadAll(p)
if err != nil {
// can't process this entry, for some reason
fmt.Fprintln(os.Stderr, err)
continue
}
filename := params["filename"]
imageUpload := images.ImageUpload{
Type: &disposition,
Bytes: bytes,
Name: &filename,
}
res.Files = append(res.Files, &imageUpload)
}
}
*p = &res
return nil
}