Chunky for Craft CMS

Usage

There is nothing to do

Chunky has no field type, no Twig tag and no template change. Once installed it decorates the uploaders Craft already builds and gets out of the way.

Where it applies

ScreenUploaderChunked
Assetsdrop zone and upload buttonyes
Any element edit screen with an Assets fieldthe field's drop zoneyes
Element editor slideoutsthe sameyes
Asset editor → Replace filethe replace uploaderyes
Element index → Replace filethe sameyes
Users → photoCraft's image uploaderno
Settings → General → site imagesCraft's image uploaderno
Another plugin's upload actionthat plugin'sno

The last three are left alone on purpose. They upload small images, and a plugin that quietly took over every upload on the site would be much harder to trust.

What happens per file

A file at or under the chunk size is posted whole to Craft's own assets/upload, exactly as it would be without Chunky installed.

A file larger than the chunk size is sliced. Each request carries one slice and a header:

Content-Range: bytes 0-4194303/25165824

Each unfinished chunk is answered with:

Range: 0-4194303

which is how the browser knows where it stands. The last chunk's response is the one Craft's own JavaScript reads, and it has the same shape Craft's upload action produces — including the filename-conflict prompt, so “Keep both / Replace it” works the same way it always did.

Retries

If a chunk fails on the network, Chunky waits, asks chunky/upload/status how many bytes the server is holding, and re-sends from there. Three goes by default, each waiting twice as long as the last.

If the failure was a refusal — a disallowed extension, a file over the maximum, no permission on the folder — there is no retry, and the message Craft would have shown is shown.

If the failure was a 413, Chunky says so specifically: something between the browser and Craft rejected the chunk as too large, and the fix is a smaller chunk size or a larger body limit on the web server or CDN. Nothing reaches the Craft log in that case, so without this the only clue is a number in the network panel.

Console commands

php craft chunky/partials           # what is part-way uploaded right now
php craft chunky/partials/cleanup   # sweep the ones nothing has touched for a while

cleanup takes --lifetime=<seconds> to override the configured lifetime. Craft's own garbage collection runs the same sweep, so on a healthy site neither command is needed — they are for a deploy that wants the runtime directory clean, and for working out where the disk went.

Where the pieces live

storage/runtime/chunky/u<user id>/<uid>.part, alongside a small .json manifest.

The per-user directory is not decoration — it is the whole of the access control. The upload identifier is generated by the browser, so it is a claim; scoping every lookup to the signed-in user's own directory means the claim can only ever name something that user already owns.