46 lines
1.8 KiB
PHP
46 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace Modules\Core\File\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Modules\Core\File\Models\File;
|
|
use Modules\Core\File\Services\FileService;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
/**
|
|
* Streams a File's bytes straight to the browser — inline by default (a
|
|
* browser-previewable type like an image opens/displays directly), or as
|
|
* a forced download with ?download=1 (e.g. an explicit "Download" button
|
|
* distinct from a thumbnail/preview link pointing at the same file). Only
|
|
* reachable via a short-lived signed URL — same auth model as
|
|
* Modules\Core\Shipping\Http\Controllers\DownloadShipmentLabelController
|
|
* (a valid signature IS the auth check, no separate staff/customer
|
|
* session check here) — so any caller that can mint a signed URL to this
|
|
* route (the storefront's own custom-field upload flow, or the admin
|
|
* order-line display) can hand a viewer a working link without this
|
|
* controller knowing anything about who they are or why they're allowed
|
|
* to see this particular file.
|
|
*
|
|
* Looks the File up manually from a plain {file} id rather than relying
|
|
* on implicit route-model-binding — registered via loadRoutesFrom() with
|
|
* no middleware group (see Providers\FileServiceProvider::boot()), so
|
|
* SubstituteBindings never runs and a type-hinted File parameter would
|
|
* silently resolve to an empty, non-existent model instead of 404ing.
|
|
*/
|
|
class DownloadFileController extends Controller
|
|
{
|
|
public function __invoke(Request $request, int $file, FileService $files): StreamedResponse
|
|
{
|
|
if (! $request->hasValidSignature()) {
|
|
abort(401);
|
|
}
|
|
|
|
$file = File::findOrFail($file);
|
|
|
|
abort_unless($files->exists($file), 404);
|
|
|
|
return $request->boolean('download') ? $files->download($file) : $files->retrieve($file);
|
|
}
|
|
}
|