How to add a file with js-ipfs in the browser using Buffer and/or Stream

From @fullmetal1 on Mon May 15 2017 04:28:23 GMT+0000 (UTC)

The current documents (https://github.com/ipfs/interface-ipfs-core/tree/master/API/files#add) mention a data array, with two elements. A ‘path’, and ‘content’. I want to know what the purpose of feeding a path to ipfs is when it has the file contents in the content object. I also want to know how I can use ipfs.files.add without the need for Node.js, since both Buffer and readable streams (AFAIK) are Node.js object types.

More to the point, I have a function in a webapp (client side, only html + js) with access to an ArrayBuffer variable that contains a files contents, as well as the filename for the file. What should I do to make ipfs.files.add work with what I have?

Copied from original issue: https://github.com/ipfs/faq/issues/257

From @diasdavid on Mon May 15 2017 06:53:05 GMT+0000 (UTC)

Hi @fullmetal1, the short answer to your question is: Did you get the chance to check js-ipfs examples, especially the transfer-files one? https://github.com/ipfs/js-ipfs/tree/master/examples/transfer-files

what the purpose of feeding a path to ipfs is when it has the file contents in the content object.

If you are adding a single file, you can leave the path as empty, but when adding a whole directory (a tree of files), we need to know the paths so that we can create the graph for you.

without the need for Node.js, since both Buffer and readable streams (AFAIK) are Node.js object types.

Both Buffer and Streams have polyfills for Browser land, see:

Any browser bundler (WebPack, Browserify and so on) will shim them for you.

Hope this helped :slight_smile: Let me know!

From @lidel on Mon May 15 2017 07:33:08 GMT+0000 (UTC)

It is worth mentioning that Buffer polyfill is already shipped with browserified js-ipfs-api
One can import it like this:

const Buffer = window.IpfsApi().Buffer

Example: ipfs/ipfs-firefox-addon/…/quick-upload.js

From @diasdavid on Mon May 15 2017 07:53:00 GMT+0000 (UTC)

Right! Same for js-ipfs

From @fullmetal1 on Mon May 15 2017 19:21:45 GMT+0000 (UTC)

thanks. I managed to convert my ArrayBuffer into a Buffer with ipfs.types.Buffer(content), and now adding files is working well. I’d also like to note that I’m not likely going to be using a browser bundler. Part of the reason I’m making my program is to be as lightweight and simple as possible (ie., user loads the page, and they can get and add files as they like).

At any rate I’m again making progress. Thanks for the help

I also find this pretty confusing.
On the CLI, the add command takes a list of files. The simplest possible case for just adding one file is

ipfs add randomfile

This in JS I’d have expected something like

node.files.add(path, callback)

For multiple files there could be

node.files.addMany([paths...], callback)

or add() could handle both cases via mixed type.

As far as I understand, providing both path and content is needed when the files to be added don’t actually exist on the local filesystem. If they do (which I’d expect to be quite common at least in the context of node apps), that’s not the simplest possible API.

Personally I’m not keen on the idea of having to use a buffer or stream to upload files to the network. This seems more like a workaround: Streaming and buffering is conventionally used for ongoing media sources, such as television or live streams. Those words may have a different meanings here… regardless, the setup looks more complicated than what myself and I imagine most web developers would expect.

The correct way feels like allowing js-ipfs to issue the equivalent of the console command “ipfs add filename”. The function ipfs.files.add already exists, but it only seems to accept a buffer / stream as data like you said… accepting a file path like I’m suggesting is mentioned, but with the note that it only works in Node.js.