Regular Files API | Lesson 7 of 8

Read a file in a directory

So far, we've used the CID of the file or directory as the path when accessing a file. However, now that we've learned we can wrap a number of files into a directory, we have a new way to address a file.

As you saw in our lesson on the wrapWithDirectory option, we can add one or more files to a new directory and, when doing so, we need to provide a name to each one of the files we add. As a result, the addAll method call returns us an array which contains the cid value for each of the files and directories created.

As mentioned earlier, it's useful to think of directories created with { wrapWithDirectory: true } as naming shortcuts, rather than as traditional file folders. Here's why:

Imagine that we called the addAll method like this, in order to add two files wrapped by a directory...

ipfs.addAll([
    {
        path: 'lists/kitty-pic-list.txt',
        content: catList
    },
    {
        path: 'cat-drinking-milk.jpg',
        content: catPic
    }
], { wrapWithDirectory: true })

...and that the addAll method returned this result:

[
  {
    "path": "lists/kitty-pic-list.txt",
    "cid": CID('Qmey7KyqDwo8BfAoVsyLbybQ8LTN3RGbvvY1zV5PeumTLV'),
    "size": 19021
  },
  {
    "path": "lists",
    "cid": CID('QmPT14mWCteuybfrfvqas2L2oin1Y2NCbwzTh9cc33GF1t'),
    "size": 1093102
  },
  {
    "path": "cat-drinking-milk.jpg",
    "cid": CID('QmexwNKUeJPmmNR7n4wSzQXrVuyeuQcQikHCHg5xM3mtRq'),
    "size": 912035
  },
  {
    "path": "",
    "cid": CID('QmP1j6shbCikCSfnQR7MzJrYdgM6ALpXJAUvkGJFrrwNew'),
    "size": 1181341
  }
]

To read the contents of the kitty-pic-list.txt file, we would now have four addressing options:

  • Using the file's own unique cid, as we've done previously:
ipfs.cat("Qmey7KyqDwo8BfAoVsyLbybQ8LTN3RGbvvY1zV5PeumTLV")
  • Using the file's full IPFS path (note how /ipfs/ has been prepended to the CID):
ipfs.cat("/ipfs/Qmey7KyqDwo8BfAoVsyLbybQ8LTN3RGbvvY1zV5PeumTLV")
  • Using an IPFS path that includes the cid of the file's containing directory (lists) and the file's path relative to that directory:
ipfs.cat("/ipfs/QmPT14mWCteuybfrfvqas2L2oin1Y2NCbwzTh9cc33GF1t/kitty-pic-list.txt")
  • Using an IPFS path that includes the cid of the top-level directory and the file's path relative to that directory:
ipfs.cat("/ipfs/QmP1j6shbCikCSfnQR7MzJrYdgM6ALpXJAUvkGJFrrwNew/lists/kitty-pic-list.txt")

These last two options allow us to include human-readable filenames in IPFS paths, and therefore offer an interesting reason why we might choose to use the wrapWithDirectory option even if we're only adding a single file.

Notice that whenever we use an IPFS path (and not just a CID) to reference a file, it's important that we include /ipfs/ at the start. This is necessary because there are other networking protocols that use the same CIDs but have different path structures, like libp2p or IPNS.

Try it!

Using the cat method, return the text contents of a file named success.txt, stored inside a fun directory which lives directly within another directory.

The CIDs associated with these directories are:

  • top-level directory: QmcmnUvVV31txDfAddgAaNcNKbrtC2rC9FvkJphNWyM7gy
  • fun directory: QmPT14mWCteuybfrfvqas2L2oin1Y2NCbwzTh9cc33GM1r

Since you don't know the CID of the file itself, you'll need to define its IPFS path by combining a directory's CID and the file's path relative to that directory.

Based on our file structure, the path could be expressed as:

  • fun/success.txt, relative to the top-level directory
  • success.txt, relative to the fun subdirectory

There are two valid ways to solve this challenge. Take your pick!

Hints:

  • In the code below we've already taken care of converting the bufferedContents to a string before returning the result, as you did yourself previously using .toString().
  • Don't forget to prepend /ipfs/ to the IPFS Path string
  • You need to concatenate all the data into a single buffer because the ipfs.cat method returns an Async Iterable. You can use the package it-to-buffer.
View SolutionReplace with SolutionClear Default Code
Update the code to complete the challenge. Click Submit to check your answer.