package dataformat import ( "bytes" "fmt" "io" "mime" "mime/multipart" ) type MultiPartForm struct { boundary string } var ( _ DataFormat = &MultiPartForm{} ) // NewMultiPartForm returns a new MultiPartForm encoder func NewMultiPartForm() *MultiPartForm { return &MultiPartForm{} } // IsType returns true if the data is MultiPartForm encoded func (m *MultiPartForm) IsType(data string) bool { // This method should be implemented to detect if the data is multipart form encoded return false } // Encode encodes the data into MultiPartForm format func (m *MultiPartForm) Encode(data map[string]interface{}) (string, error) { var b bytes.Buffer w := multipart.NewWriter(&b) if err := w.SetBoundary(m.boundary); err != nil { return "", err } for key, value := range data { var fw io.Writer var err error // Add field if fw, err = w.CreateFormField(key); err != nil { return "", err } if _, err = fw.Write([]byte(value.(string))); err != nil { return "", err } } w.Close() return b.String(), nil } // ParseBoundary parses the boundary from the content type func (m *MultiPartForm) ParseBoundary(contentType string) error { _, params, err := mime.ParseMediaType(contentType) if err != nil { return err } m.boundary = params["boundary"] if m.boundary == "" { return fmt.Errorf("no boundary found in the content type") } return nil } // Decode decodes the data from MultiPartForm format func (m *MultiPartForm) Decode(data string) (map[string]interface{}, error) { // Create a buffer from the string data b := bytes.NewBufferString(data) // The boundary parameter should be extracted from the Content-Type header of the HTTP request // which is not available in this context, so this is a placeholder for demonstration. // You will need to pass the actual boundary value to this function. r := multipart.NewReader(b, m.boundary) form, err := r.ReadForm(32 << 20) // 32MB is the max memory used to parse the form if err != nil { return nil, err } defer func() { _ = form.RemoveAll() }() result := make(map[string]interface{}) for key, values := range form.Value { if len(values) > 1 { result[key] = values } else { result[key] = values[0] } } for key, files := range form.File { fileContents := []interface{}{} for _, fileHeader := range files { file, err := fileHeader.Open() if err != nil { return nil, err } defer file.Close() buffer := new(bytes.Buffer) if _, err := buffer.ReadFrom(file); err != nil { return nil, err } fileContents = append(fileContents, buffer.String()) } result[key] = fileContents } return result, nil } // Name returns the name of the encoder func (m *MultiPartForm) Name() string { return "multipart/form-data" }