Download the PHP package shetabit/chunky without Composer
On this page you can find all versions of the php package shetabit/chunky. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download shetabit/chunky
More information about shetabit/chunky
Files in shetabit/chunky
Package chunky
Short Description resumable chunk upload manager
License MIT
Homepage https://github.com/shetabit/chunky
Informations about the package chunky
Chunky :)
handle and upload files in base64 data URI, base64 json format and normal file formats.
This package supports PHP 8.4+ and has no dependencies of its own, so it can be used in any PHP framework —
Laravel, Symfony and the rest — as well as in no framework at all.
Chunky can be used to handle input/output file streams, both of
inputandoutputstreams can be multi-chunk and resumable.
List of contents
- Install
- A running example
- How to use
- Stream output
- Stream input
- The formats a chunk can be sent in
- Sending chunks as plain uploads
- Validations
- Events
- Collect and store input files
- Create stream in Laravel Framework
- Download stream
- Upload stream
- Errors
- Testing
- Change log
- Contributing
- Security
- Credits
- License
Install
Via Composer
A running example
There is a small application in examples/ that uploads a file chunk by chunk — with a pause and a resume
— and hands it back out as a resumable download. It is an application of its own, with its own composer.json and
its own container, and it is not installed with the package.
See examples/README.md for what to try and how the pieces fit together.
how-to-use
this package can be used in order to stream input/output files.
- stream output files (stream download)
- stream input files (stream upload)
Stream output
outputs can be streamed using Shetabit\Chunky\Classes\StreamOut like the below
the download stream will be multi-chunk and resumable as you see in the below screenshot (in Internet download manager)
The stream reads the Range header of the request on its own. If your framework hands you the headers of a request
itself, you can pass the header along instead:
A client that asks for a part of the file receives a 206 Partial Content, one that asks for a range that is not
there receives a 416 Requested Range Not Satisfiable, and one that asks for several ranges at once receives them as
a multipart/byteranges response.
The stream can be throttled, and the size of the buffer it writes can be changed:
Stream input
input files can be uploaded chunk by chunk and resumable. you can collect files and upload them like the below
after uploading files, they will be in $uploads in array format: one entry per chunk, each of them holding the
path the chunk was written to, the range of the destination it was written at ([offset, length]), the file
itself and how much of it is assembled so far.
the upload stream is multi-chunk and resumable: an upload that was paused — or whose browser was closed — starts again at the byte it stopped on, because every chunk says which bytes of the file it holds and the server writes it exactly there.
A chunk carries the bytes of the whole file it holds in its range (1024-2047), and that is where it is written —
whatever order the chunks arrive in. The name a chunk is stored under is its own name with everything but the file
name cut off it, so a client can not write outside of the upload directory.
The screenshot above is the example that comes with the package; make up in examples/ runs it.
The formats a chunk can be sent in
The same input can be sent in three formats, and all three of them are collected together:
| format | where it is read from | example |
|---|---|---|
| an uploaded file | $_FILES[$inputName] |
<input name="media" type="file"> |
| a base64 data uri | $_REQUEST[$inputName] |
data:image/png;name=avatar.png;range=0-1023;base64,iVBORw0KGgo... |
| a json payload | $_REQUEST[$inputName] |
{"mime":"image/png","meta":{"name":"avatar.png","range":"0-1023"},"data":"iVBORw0KGgo..."} |
The name, the range and the size of the meta section of a data uri and of the meta of a json payload become
the attributes of the file the package hands you.
Sending chunks as plain uploads
A data uri and a json payload carry the range and the size of their file in their meta section. A plain upload has
nowhere to put them — $_FILES holds a name, a content type and the size of the chunk itself — so they travel next to
the upload as fields of their own, and ChunkedUploadCollector puts them back together:
One chunk per request, the fields hold one value each:
Several files in one request — name="media[]", name="range[]" — and they hold one value per chunk, in the order
the files were sent in:
A field holding a single value belongs to every chunk of the request; a field holding a list belongs to the chunks one
by one. What the request says wins over what a chunk says about itself — a client naming the size of the whole file is
telling the server something $_FILES can not know, where the size of the chunk sits under the same name.
range and size are read by default. Any attribute can be, and out of a field of another name:
name and mime are not read by default on purpose: $_FILES holds both already, and a form that happens to have a
field called name next to its upload would otherwise rename what it uploads. The fields are read from $_POST
unless a third argument says where else to read them from.
Validations
An incoming stream can be told what it takes. Every chunk is checked before anything of it is written, and a request that carries a single chunk too many is turned away whole, so it leaves no half a file behind.
They can be added afterwards as well, with addValidation() and addValidations(), and $stream->validate() runs
them on their own — it looks a request over and writes nothing either way.
| validation | what it checks |
|---|---|
Size($maximum, $minimum = 0) |
The size the client announced for the whole file, and the bytes of the chunk that arrived. Sizes are written as 5M, 512 KB, 1.5g or a plain number of bytes. |
Extension([...]) |
What the file is called. Case is ignored and the dot is optional. |
MimeType([...], detect: true) |
What the file says it is — and, for a chunk that holds the beginning of its file, what its bytes say it is. |
A chunk out of the middle of a file has none of the bytes that give a file away, so MimeType can only look into the
chunk that starts the file. detect: false turns the looking off and takes the client's word.
Your own validation is any class that implements Shetabit\Chunky\Contracts\ValidationInterface — throw a
ValidationFailedException to turn a file away:
Events
An incoming stream calls you back around each of the two things it does to a chunk:
$assembled is what makes the last chunk of a file recognisable, which is usually where the interesting part of an
application starts:
The same number comes back from process(), under assembled, next to the path, the range and the file of
every chunk that was stored.
Collect and store input files
you can collect input files and then upload them as you want.
saveAs() takes the offset of the destination the file is written at, and how many of its bytes to write:
Create stream in Laravel Framework
Resumable chunk download stream example in Laravel
create a controller like the below and create an indirect resumable file stream in Laravel.
in this example we have a File eloquent model.
Resumable chunk upload stream example in Laravel
Errors
Everything the package throws extends Shetabit\Chunky\Exceptions\ChunkyException, so a single catch covers all of
it:
| exception | when it is thrown |
|---|---|
FileNotFoundException |
a file that has to be read is not there, or the upload directory does not exist |
FileAccessException |
a file exists but could not be opened or written to |
InvalidDataException |
a data uri or a json payload could not be decoded |
ValidationFailedException |
a file was turned away by a validation; getErrors() says everything that is wrong and getChunk() hands back the file, when a single one was at fault |
Testing
Every pull request and every push to master is checked by GitHub Actions: the test suite runs on
PHP 8.4 and 8.5 (against both the lowest and the highest supported dependencies), the coding style is checked with
PHP_CodeSniffer, the sources are analysed with PHPStan and the code coverage of the test suite is measured and has to
stay above 90%.
Next to the unit tests there are feature tests that send a whole file chunk by chunk — in every order the chunks can arrive in, and in all three formats the package reads — and download it again range by range, with an interruption in the middle.
You can run the same checks locally. With PHP and Composer installed on your machine:
If you would rather not install PHP on your machine, the shipped Dockerfile and Makefile run everything inside a
container:
Another PHP version can be used with make test PHP_VERSION=8.5.
Change log
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONDUCT for details.
Security
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
Credits
- Mahdi khanzadi
- All Contributors
License
The MIT License (MIT). Please see License File for more information.
All versions of chunky with dependencies
ext-fileinfo Version *
ext-json Version *
ext-mbstring Version *