Regular Files API | Lesson 4 of 8

Read the contents of a file

In the previous lesson, you saw that each file added to IPFS has its own unique cid derived from its content. This CID (Content Identifier), can be used like an address to access the file. If you know a file's CID, you can use the cat method provided by the Regular IPFS Files API -- similar to the one you may have seen previously in Unix-style systems -- to retrieve its contents like so:

ipfs.cat(ipfsPath, [options])

An IPFS path can take several forms (you can read about them in the Files API documentation). In this lesson, we'll use the simplest one: the cid present in the object we receive for a file when the ipfs.add method is called. You may remember from the previous lesson that the add method returned both path and cid values for each file you added to IPFS. We'll learn more about the difference between these two values later.

The cat method first searches your own node for the file requested, and if it can't find it there, it will attempt to find it on the broader IPFS network. Because of the way cryptographic hashing works, the content you're searching for is guaranteed to match the file found, regardless of which peer is hosting it.

The cat method returns an Async Iterable that iterates over the file's chunks of data, i.e. Buffers.

A Buffer is just a raw collection of bytes and as such doesn't make any assumptions about encodings or the type of data it contains. However, if we know the file being retrieved is a plain text file such as a .txt, we can convert its buffered contents to a UTF-8 string (an interpretation of those raw bytes) by calling the JavaScript method .toString().

But since we have multiple buffers of the same file, we need to reassemble them (concatenate) into a single buffer before converting it into a string. The it-to-buffer package can do just that: iterate over all of the chunks of the file and put them back together for us.

So if you had the CID for a text file in an IPFS node, you could retrieve the file's contents as a readable string like so:

// the toBuffer variable is globally available (just like ipfs)

const bufferedContents = await toBuffer(ipfs.cat('QmWCscor6qWPdx53zEQmZvQvuWQYxx1ARRCXwYVE4s9wzJ')) // returns a Buffer
const stringContents = bufferedContents.toString() // returns a string

When you're ready to try this in the real world, you should note that the above example can result in heavy memory usage, depending on the contents of the file being read. If you're working with large files and find this to be the case, you might want to skip using the it-to-buffer package and instead process each chunk of data iteratively. The main reason IPFS now returns Async Iterables is to provide a built-in option for dealing with potential performance issues. In ProtoSchool tutorials, our code challenges use small files, so we can concatenate everything without worrying about performance.

not yet startedTry it!

For this challenge, we've added a plain text file to your IPFS node for you, and its CID is the following string:

QmWCscor6qWPdx53zEQmZvQvuWQYxx1ARRCXwYVE4s9wzJ

Using the cat function, retrieve the file's contents and return them as a string.

Hints:

  • The CID we provide is a string, so it needs to be placed inside quotes. Also, don't forget to convert the buffered contents of the text file to a string using .toString() before returning your result.
  • You need to concatenate all the chunks of data because the ipfs.cat method returns an Async Iterable. You can use the package it-to-buffer to achieve this.
View SolutionReplace with SolutionClear Default Code
Update the code to complete the challenge. Click Submit to check your answer.