PHP code example of pinoox / pinion

1. Go to this page and download the library: Download pinoox/pinion library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

pinoox / pinion example snippets


use Pinoox\Pinion\Pinion;

Pinion::configure(['storage_path' => '/tmp/pinion']);

$handler = Pinion::http(['destination' => 'uploads/videos']);

$handler->init($_POST);           // POST …/init
$handler->upload($_POST, $file);  // POST …/upload  (one chunk)
$handler->complete($_POST);       // POST …/complete


use Pinoox\Pinion\Pinion;

h' => __DIR__ . '/storage/pinion-temp']);

$handler = Pinion::http(['destination' => 'uploads/inbox']);

$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];

$response = match (true) {
    $method === 'POST' && str_ends_with($uri, '/init')
        => $handler->init($_POST),

    $method === 'POST' && str_ends_with($uri, '/upload')
        => $handler->upload($_POST, $_FILES['chunk'] ?? null),

    $method === 'POST' && str_ends_with($uri, '/complete')
        => $handler->complete($_POST),

    $method === 'GET' && preg_match('#/status/([a-f0-9-]+)$#', $uri, $m)
        => $handler->status($m[1]),

    $method === 'POST' && preg_match('#/abort/([a-f0-9-]+)$#', $uri, $m)
        => $handler->abort($m[1]),

    default => ['success' => false, 'error' => ['code' => 'PINION_UNKNOWN', 'message' => 'not_found']],
};

header('Content-Type: application/json');
echo json_encode($response);

use Pinoox\Pinion\Pinion;
use Pinoox\Pinion\Support\NativePathResolver;

Pinion::configure([
    'storage_path' => '/var/www/storage/pinion-temp',
    'chunk_size' => 5 * 1024 * 1024,
    'verify_chunks' => true,
], new NativePathResolver('/var/www'));

$handler = Pinion::http([
    'destination' => 'uploads/documents',
    'extensions' => ['pdf', 'docx'],
]);

$result = Pinion::begin()
    ->filename('report-Q1.pdf')
    ->size(48_000_000)
    ->to('uploads/documents')
    ->extensions(['pdf'])
    ->fingerprint($clientFingerprint)
    ->chunkSize('5MB')
    ->init();

if (!$result->success) {
    exit($result->error);
}

$uploadId = $result->session->id;

foreach ($result->session->missingIndexes() as $index) {
    Pinion::manager()->receive($uploadId, $index, $chunkBinary, $chunkHash);
}

$complete = Pinion::manager()->complete($uploadId);
// $complete->path → absolute path on disk

use Pinoox\Component\Kernel\Controller\ApiController;
use Pinoox\Component\Pinion\Concerns\PinionUploadActions;

class PinionController extends ApiController
{
    use PinionUploadActions;

    protected function pinionDefaults(): array
    {
        return [
            'destination' => 'uploads/media',
            'extensions' => ['mp4', 'mov', 'webm'],
            'mode' => 'auto',       // S3 when app disk is s3
            'record' => true,       // create pinx_file row
            'access' => 'public',
            'group' => 'media',
        ];
    }
}

protected function pinionDefaults(): array
{
    return [
        'destination' => 'downloads/packages/manual',
        'extensions' => ['pinx'],
        'mode' => 'local',
        'storage' => false,
        'record' => false,
    ];
}

use App\Http\Controllers\PinionUploadController;

Route::prefix('api/v1/upload')->group(function () {
    Route::post('init', [PinionUploadController::class, 'init']);
    Route::post('upload', [PinionUploadController::class, 'upload']);
    Route::post('complete', [PinionUploadController::class, 'complete']);
    Route::get('status/{uploadId}', [PinionUploadController::class, 'status']);
    Route::post('abort/{uploadId}', [PinionUploadController::class, 'abort']);
});

namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Pinoox\Pinion\HttpHandler;

final class PinionUploadController extends Controller
{
    public function __construct(private readonly HttpHandler $pinion) {}

    public function init(Request $request): JsonResponse
    {
        return $this->json($this->pinion->init($request->all()));
    }

    public function upload(Request $request): JsonResponse
    {
        return $this->json($this->pinion->upload($request->all(), $request->file('chunk')));
    }

    public function complete(Request $request): JsonResponse
    {
        return $this->json($this->pinion->complete($request->all()));
    }

    public function status(string $uploadId): JsonResponse
    {
        return $this->json($this->pinion->status($uploadId));
    }

    public function abort(string $uploadId): JsonResponse
    {
        return $this->json($this->pinion->abort($uploadId));
    }

    private function json(array $payload): JsonResponse
    {
        $status = (int) ($payload['status'] ?? ($payload['success'] ? 200 : 400));

        return response()->json(
            $payload['success'] ? ($payload['data'] ?? null) : ($payload['error'] ?? $payload),
            $status,
        );
    }
}

use Pinoox\Pinion\Laravel\Facades\Pinion;

$result = Pinion::begin()
    ->filename('dataset-export.csv')
    ->size(filesize($path))
    ->to('exports')
    ->init();

$manager = Pinion::manager();

$result = $manager->init(
    filename: 'archive.zip',
    size: 1_073_741_824,
    destination: 'uploads/archives',
    extensions: ['zip'],
    fingerprint: $clientFingerprint,
);

$session = $result->session;
$manager->receive($session->id, 0, $binary, $chunkHash);
$manager->receive($session->id, 1, $binary, $chunkHash);
// …

$done = $manager->complete($session->id);
echo $done->path;

$handler = Pinion::http([
    'destination' => 'uploads/videos',
    'extensions' => ['mp4', 'mov'],
]);
// client can override destination per init, or use these defaults

use Pinoox\Pinion\Contract\PathResolverInterface;

final class AppPathResolver implements PathResolverInterface
{
    public function resolve(string $reference): string
    {
        return match ($reference) {
            'videos' => '/data/media/videos',
            'documents' => '/data/media/docs',
            default => '/data/media/' . ltrim($reference, '/'),
        };
    }
}

Pinion::configure($config, new AppPathResolver());

$session = Pinion::manager()->status($uploadId);
// → progress, missing_indexes, bytes_received

$pending = Pinion::manager()->list('pending');
$removed = Pinion::manager()->cleanExpired();
Pinion::manager()->abort($uploadId);

POST {baseURL}/init
POST {baseURL}/upload
POST {baseURL}/complete
GET  {baseURL}/status/{upload_id}
POST {baseURL}/abort/{upload_id}
bash
php pinoox pinion:list
php pinoox pinion:info {upload_id}
php pinoox pinion:clean --abort={upload_id}
bash
php artisan vendor:publish --tag=pinion-config
bash
php pinoox pinion:list
php pinoox pinion:info a1b2c3d4-...
php pinoox pinion:clean
php pinoox pinion:clean --abort=a1b2c3d4-...

packages/pinion/
├── composer.json           # pinoox/pinion 1.1.0 (Packagist)
├── client/                 # @pinooxhq/pinion-client 1.2.0 (npm)
│   ├── src/                # createClient, transport, checksum, …
│   ├── types/              # TypeScript definitions
│   ├── package.json
│   └── README.md           # npm client guide (publish, API)
├── config/pinion.php       # default PHP config
├── src/                    # PHP protocol engine
│   ├── Pinion.php          # entry point
│   ├── Manager.php         # core engine
│   ├── HttpHandler.php     # HTTP adapter
│   ├── Builder.php         # fluent init
│   ├── Session.php / Result.php
│   ├── Laravel/            # service provider + facade
│   └── Support/            # NativePathResolver, …
├── tests/
└── README.md               # this file