Add chunked uploads and raise storage rate to GHS 0.30/GB/month.
Deploy Ladill Transfer / deploy (push) Successful in 39s
Deploy Ladill Transfer / deploy (push) Successful in 39s
Large files upload in 5 MB chunks (hosting file manager pattern) for the transfer UI and Ladill Mail S2S API, with no app-level file size cap when TRANSFER_MAX_FILE_BYTES=0. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Transfer;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\Upload\ChunkedUploadService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use RuntimeException;
|
||||
|
||||
class ChunkedUploadController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private ChunkedUploadService $uploads,
|
||||
) {}
|
||||
|
||||
public function init(Request $request): JsonResponse
|
||||
{
|
||||
$account = ladill_account();
|
||||
|
||||
$validated = $request->validate([
|
||||
'filename' => 'required|string|max:255',
|
||||
'filesize' => 'required|integer|min:1',
|
||||
]);
|
||||
|
||||
$uploadId = $this->uploads->init($this->ownerKey($account->id), [
|
||||
'filename' => $validated['filename'],
|
||||
'filesize' => (int) $validated['filesize'],
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'upload_id' => $uploadId,
|
||||
]);
|
||||
}
|
||||
|
||||
public function chunk(Request $request): JsonResponse
|
||||
{
|
||||
$account = ladill_account();
|
||||
$ownerKey = $this->ownerKey($account->id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'upload_id' => 'required|string|uuid',
|
||||
'chunk_index' => 'required|integer|min:0',
|
||||
'chunk_size' => 'required|integer|min:1',
|
||||
'chunk' => 'required|file|max:10240',
|
||||
]);
|
||||
|
||||
$chunk = $request->file('chunk');
|
||||
if ($chunk === null) {
|
||||
return response()->json(['success' => false, 'error' => 'Chunk missing.'], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
$received = $this->uploads->receiveChunk(
|
||||
$validated['upload_id'],
|
||||
$ownerKey,
|
||||
(int) $validated['chunk_index'],
|
||||
$chunk,
|
||||
(int) $validated['chunk_size'],
|
||||
);
|
||||
} catch (RuntimeException $e) {
|
||||
return response()->json(['success' => false, 'error' => $e->getMessage()], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'chunk_index' => (int) $validated['chunk_index'],
|
||||
'chunks_received' => $received,
|
||||
]);
|
||||
}
|
||||
|
||||
public function finalize(Request $request): JsonResponse
|
||||
{
|
||||
$account = ladill_account();
|
||||
$ownerKey = $this->ownerKey($account->id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'upload_id' => 'required|string|uuid',
|
||||
'total_chunks' => 'required|integer|min:1',
|
||||
]);
|
||||
|
||||
try {
|
||||
$this->uploads->finalize(
|
||||
$validated['upload_id'],
|
||||
$ownerKey,
|
||||
(int) $validated['total_chunks'],
|
||||
);
|
||||
} catch (RuntimeException $e) {
|
||||
return response()->json(['success' => false, 'error' => $e->getMessage()], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'upload_id' => $validated['upload_id'],
|
||||
]);
|
||||
}
|
||||
|
||||
private function ownerKey(int $userId): string
|
||||
{
|
||||
return 'user:'.$userId;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user