@@ -4,6 +4,7 @@ import isFormData from "./util/isFormData"
44import isFile from "./util/isFile"
55
66import { FormDataLike } from "./FormDataLike"
7+ import { FileLike } from "./FileLike"
78
89export class Encoder {
910 /**
@@ -126,8 +127,57 @@ export class Encoder {
126127 return length + this . #footer. byteLength
127128 }
128129
130+ /**
131+ * Creates an iterator allowing to go through form-data parts (with metadata).
132+ * This method **will not** read the files.
133+ *
134+ * Using this method, you can convert form-data content into Blob:
135+ *
136+ * @example
137+ *
138+ * import {Readable} from "stream"
139+ *
140+ * import {Encoder} from "form-data-encoder"
141+ *
142+ * import {FormData} from "formdata-polyfill/esm-min.js"
143+ * import {fileFrom} from "fetch-blob/form.js"
144+ * import {File} from "fetch-blob/file.js"
145+ * import {Blob} from "fetch-blob"
146+ *
147+ * import fetch from "node-fetch"
148+ *
149+ * const fd = new FormData()
150+ *
151+ * fd.set("field", "Just a random string")
152+ * fd.set("file", new File(["Using files is class amazing"]))
153+ * fd.set("fileFromPath", await fileFromPath("path/to/a/file.txt"))
154+ *
155+ * const encoder = new Encoder(fd)
156+ *
157+ * const options = {
158+ * method: "post",
159+ * body: new Blob(encoder, {type: encoder.contentType})
160+ * }
161+ *
162+ * const response = await fetch("https://httpbin.org/post", options)
163+ *
164+ * console.log(await response.json())
165+ */
166+ * values ( ) : Generator < Uint8Array | FileLike , void , undefined > {
167+ for ( const [ name , value ] of this . #form. entries ( ) ) {
168+ yield this . #getFieldHeader( name , value )
169+
170+ yield isFile ( value ) ? value : this . #encoder. encode ( String ( value ) )
171+
172+ yield this . #CRLF_BYTES
173+ }
174+
175+ yield this . #footer
176+ }
177+
129178 /**
130179 * Creates an async iterator allowing to perform the encoding by portions.
180+ * This method **will** also read files.
131181 *
132182 * @example
133183 *
@@ -157,22 +207,26 @@ export class Encoder {
157207 * console.log(await response.json())
158208 */
159209 async * encode ( ) : AsyncGenerator < Uint8Array , void , undefined > {
160- for ( const [ name , value ] of this . #form) {
161- yield this . #getFieldHeader( name , value )
162-
163- if ( isFile ( value ) ) {
164- yield * value . stream ( )
210+ for ( const part of this . values ( ) ) {
211+ if ( isFile ( part ) ) {
212+ yield * part . stream ( )
165213 } else {
166- yield this . #encoder . encode ( String ( value ) )
214+ yield part
167215 }
168-
169- yield this . #CRLF_BYTES
170216 }
217+ }
171218
172- yield this . #footer
219+ /**
220+ * Creates an iterator allowing to read through the encoder data using for...of loops
221+ */
222+ [ Symbol . iterator ] ( ) : Generator < Uint8Array | FileLike , void , undefined > {
223+ return this . values ( )
173224 }
174225
175- [ Symbol . asyncIterator ] ( ) {
226+ /**
227+ * Creates an **async** iterator allowing to read through the encoder data using for-await...of loops
228+ */
229+ [ Symbol . asyncIterator ] ( ) : AsyncGenerator < Uint8Array , void , undefined > {
176230 return this . encode ( )
177231 }
178232}
0 commit comments