def read(consumer, offset=0, size=None):
    """Download a portion (possibly all) of the file's contents, making
        them available to the given IConsumer. Return a Deferred that fires
        (with the consumer) when the consumer is unregistered (either because
        the last byte has been given to it, or because the consumer threw an
        exception during write(), possibly because it no longer wants to
        receive data). The portion downloaded will start at 'offset' and
        contain 'size' bytes (or the remainder of the file if size==None). It
        is an error to read beyond the end of the file: callers must use
        get_size() and clip any non-default offset= and size= parameters. It
        is permissible to read zero bytes.

        The consumer will be used in non-streaming mode: an IPullProducer
        will be attached to it.

        The consumer will not receive data right away: several network trips
        must occur first. The order of events will be::

         consumer.registerProducer(p, streaming)
          (if streaming == False)::
           consumer does p.resumeProducing()
            consumer.write(data)
           consumer does p.resumeProducing()
            consumer.write(data).. (repeat until all data is written)
         consumer.unregisterProducer()
         deferred.callback(consumer)

        If a download error occurs, or an exception is raised by
        consumer.registerProducer() or consumer.write(), I will call
        consumer.unregisterProducer() and then deliver the exception via
        deferred.errback(). To cancel the download, the consumer should call
        p.stopProducing(), which will result in an exception being delivered
        via deferred.errback().

        See src/allmydata/util/consumer.py for an example of a simple
        download-to-memory consumer.
        """
