Opinionated abstraction around PHP streams implementing PSR-7 StreamInterface. It aims to improve working with files or remote streams in unified way.
Heavily inspired by guzzle/psr7.
Via Composer
$ composer require digitalcz/streamsAll streams implement DigitalCz\Streams\StreamInterface, which extends PSR-7
Psr\Http\Message\StreamInterface and adds a few convenience methods
(copy(), void-returning close()/seek(), …).
A wrapper around any PHP stream resource. Use Stream::from() to build one from
a string, a resource or another PSR-7 stream — the data is held in php://temp.
use DigitalCz\Streams\Stream;
// From a string
$stream = Stream::from('Hello world');
echo $stream->getContents(); // "Hello world"
// From an existing resource
$stream = Stream::from(fopen('php://memory', 'rb+'));
// From another PSR-7 stream
$stream = Stream::from($psrStream);
// Wrapping a resource directly (optionally with a known size)
$stream = new Stream(fopen('data.bin', 'rb'));
// Copy another stream into this one (returns bytes written)
$bytes = $stream->copy($otherStream);A stream backed by a real file on disk. Adds getPath() and delete().
use DigitalCz\Streams\File;
$file = new File('/path/to/file.txt'); // opened with mode "rb+" by default
echo $file->getPath();
// Build a file from a string / resource / PSR-7 stream.
// Write a string to a new temp file (the string is never treated as a path).
$file = File::fromString('contents written to a temp file');
// File::from() also accepts a string, but an existing path opens that file,
// otherwise it is the content. Never pass untrusted input to it.
$file = File::from($psrStreamOrResource);
$temp = File::temp(); // empty file in the system temp dir
$file->delete(); // close and unlinkLike File, but backed by tmpfile() — the underlying file is removed
automatically once the stream handle is closed.
use DigitalCz\Streams\TempFile;
$temp = TempFile::from('temporary content');
echo $temp->getPath();
$temp->close(); // file is deleted on closeWraps a non-seekable / one-shot source stream and buffers what it reads into
php://temp, so the source can be re-read and seeked. It is read-only.
use DigitalCz\Streams\BufferedStream;
$buffered = new BufferedStream($nonSeekableSource);
$head = $buffered->read(1024);
$buffered->rewind(); // works even if the source could not seek
$all = $buffered->getContents();Read-only view of a window of another stream: at most $limit bytes starting
at $offset. Size, position and seeking are relative to the window.
use DigitalCz\Streams\LimitStream;
$window = new LimitStream($stream, limit: 100, offset: 50);
$chunk = $window->getContents(); // bytes 50–149 of $streamReads several streams one after another as if they were one (seekable parts are read from the start). It is read-only, seekable only if all parts are, and its size is unknown if any part's size is.
use DigitalCz\Streams\AppendStream;
use DigitalCz\Streams\Stream;
$stream = new AppendStream(Stream::from('header'), $body, Stream::from('footer'));
$all = $stream->getContents();Turns a StreamInterface back into a native PHP stream resource, usable with
any function that expects one (fread, fgets, stream_copy_to_stream, …).
use DigitalCz\Streams\StreamWrapper;
$resource = StreamWrapper::from($stream);
$line = fgets($resource);Hashes or detects the MIME type of any PSR-7 stream without loading it all into
memory. Seekable streams are read from the start and their position is restored.
Non-seekable streams are read from the current position and the bytes read are
consumed — wrap them in BufferedStream if you need them again.
use DigitalCz\Streams\StreamInfo;
$sha256 = StreamInfo::hash($stream, 'sha256'); // any algorithm from hash_algos()
$mimeType = StreamInfo::mimeType($stream); // e.g. "application/pdf", requires ext-fileinfoPlease see CHANGELOG for more information on what has changed recently.
$ composer csfix # fix codestyle
$ composer checks # run all checks
# or separately
$ composer tests # run phpunit
$ composer phpstan # run phpstan
$ composer cs # run codesnifferPlease see CONTRIBUTING for details.
If you discover any security related issues, please email devs@digital.cz instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.