Embracing web native FormData / File where possible #3029
Description
As discussed at #2838 (comment) mainstream browsers today do not yet support passingReadableStream
as request body. To workaround this limitation currently JS-IPFS encodes stream of content (on ipfs.add / ipfs.write) into multipart/form-data by buffering it:
js-ipfs/packages/ipfs-http-client/src/add.js
Lines 13 to 23 in cb5b9ec
js-ipfs/packages/ipfs-http-client/src/lib/multipart-request.js
Lines 58 to 64 in cb5b9ec
js-ipfs/packages/ipfs-http-client/src/lib/to-stream.browser.js
Lines 11 to 21 in cb5b9ec
This is problematic for webui for instance as some files may not fit into memory or exceed browser quota.
Modern browsers do have native FormData
and File
/ Blob
primitives that if used carefully can facilitate streaming. It appears that in the past browser loaded all of the FormData / File / Blob content during fetch
despite not reading it. However that evidently had being fixed and modern browsers (Tested with Firefox, Chrome, Safari) no longer exhibit that problem.
Following example was used to verify this behavior
https://ipfs.io/ipfs/QmWVrTAeA1FqRSK3owpCfvB69wsz2Dbr2THK6ehn5uEKbp
On my Mac I do not observe visible increase memory when I uploading 5 Gig file (across mentioned browsers). I also observe streaming behavior as as file size change in WebUI is changing during upload:
This investigation suggests that there is an opportunity to avoid buffering overhead in browsers. It also appears that doing it for ipfs.files.write
should be fairly straight forward since it always writes a single file.
For ipfs.add
things appear more complicated, as headers need to be added to each multipart part (E.g. unix mode & mtime). Some investigation is required to see how visible that is with native FormData
. There are also some concerns about supporting directory structures.