code: def DownloadDir(aff4_path, output_dir, bufsize=8192, preserve_path=True):
    
    if not os.path.isdir(output_dir):
      os.makedirs(output_dir)
    fd = aff4.FACTORY.Open(aff4_path)
    for child in fd.OpenChildren():
      if preserve_path:
        # Get a full path without the aff4:
        full_dir = utils.JoinPath(output_dir, child.urn.Path())
        full_dir = os.path.dirname(full_dir)
        if not os.path.isdir(full_dir):
          os.makedirs(full_dir)
        outfile = os.path.join(full_dir, child.urn.Basename())
      else:
        outfile = os.path.join(output_dir, child.urn.Basename())
      logging.info(u"Downloading %s to %s", child.urn, outfile)
      with open(outfile, "wb") as out_fd:
        try:
          buf = child.Read(bufsize)
          while buf:
            out_fd.write(buf)
            buf = child.Read(bufsize)
        except IOError as e:
          logging.error("Failed to read %s. Err: %s", child.urn, e)
docs: Take an aff4 path and download all files in it to output_dir.
  
    Args:
      aff4_path: Any aff4 path as a string
      output_dir: A local directory to write to, will be created if not there.
      bufsize: Buffer size to use.
      preserve_path: If set all paths will be created.  Note that this works for
        collections as well. It will download all files in the collection.  This
        only downloads files that are already in the datastore, it doesn't queue
        anything on the client.