BuildFormdata constructs a multipart form data payload for file upload. If isStdin is true, the file content is read from stdin. Top-level keys from dataJSON are added as text form fields.
(fileIO fileio.FileIO, fieldName, filePath string, isStdin bool, stdin io.Reader, dataJSON any)
| 94 | // If isStdin is true, the file content is read from stdin. |
| 95 | // Top-level keys from dataJSON are added as text form fields. |
| 96 | func BuildFormdata(fileIO fileio.FileIO, fieldName, filePath string, isStdin bool, stdin io.Reader, dataJSON any) (*larkcore.Formdata, error) { |
| 97 | fd := larkcore.NewFormdata() |
| 98 | |
| 99 | if isStdin { |
| 100 | if stdin == nil { |
| 101 | return nil, errs.NewValidationError(errs.SubtypeFailedPrecondition, "--file: stdin is not available"). |
| 102 | WithParam("--file"). |
| 103 | WithHint("pipe the file content to stdin, or pass a file path instead of \"-\"") |
| 104 | } |
| 105 | data, err := io.ReadAll(stdin) |
| 106 | if err != nil { |
| 107 | return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--file: failed to read stdin: %v", err). |
| 108 | WithParam("--file"). |
| 109 | WithCause(err) |
| 110 | } |
| 111 | if len(data) == 0 { |
| 112 | return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--file: stdin is empty"). |
| 113 | WithParam("--file"). |
| 114 | WithHint("pipe non-empty file content to stdin") |
| 115 | } |
| 116 | fd.AddFile(fieldName, bytes.NewReader(data)) |
| 117 | } else { |
| 118 | f, err := fileIO.Open(filePath) |
| 119 | if err != nil { |
| 120 | return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "cannot open file: %s", filePath). |
| 121 | WithParam("--file"). |
| 122 | WithCause(err) |
| 123 | } |
| 124 | defer f.Close() |
| 125 | data, err := io.ReadAll(f) |
| 126 | if err != nil { |
| 127 | return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "--file: failed to read %s: %v", filePath, err). |
| 128 | WithParam("--file"). |
| 129 | WithCause(err) |
| 130 | } |
| 131 | fd.AddFile(fieldName, bytes.NewReader(data)) |
| 132 | } |
| 133 | |
| 134 | // Add top-level JSON keys as text form fields. |
| 135 | if m, ok := dataJSON.(map[string]any); ok { |
| 136 | for k, v := range m { |
| 137 | fd.AddField(k, formatFormFieldValue(v)) |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | return fd, nil |
| 142 | } |
| 143 | |
| 144 | // formatFormFieldValue renders a JSON-unmarshalled value as a multipart form |
| 145 | // field string. float64 is handled specially: fmt's default %v/%g switches to |