Nagy fájlok feltöltése megszakadás nélkül Laravelben
A média szolgáltatásomban az első verzióban a feltöltés egyetlen kérésben ment. Nagy videóknál ez rendszeresen megszakadt, mert a szerver előtt lévő hálózati réteg egy kérés méretét és idejét is korlátozza: nagyjából 100 MB-nál és 100 másodpercnél elvágja a kapcsolatot.
A megoldás: darabok
A böngésző 20 MB-os darabokra vágja a fájlt, és sorban küldi őket. Három lépés van.
- init: a szerver megkapja a fájlnevet, a méretet és a darabszámot, és ad egy feltöltés-azonosítót.
- chunk: egy darab, indexszel. A szerver sorszámozott fájlként elmenti.
- complete: a szerver sorrendben összefűzi a darabokat, ellenőrzi a méretet, és átadja a meglévő feldolgozónak.
Az újrapróbálás legyen ártalmatlan
A lényeg az, hogy ugyanannak az indexnek az újraküldése felülírja a darabot. Így a böngésző nyugodtan újrapróbálhat. Nálam négyszer próbálkozik, egyre hosszabb várakozással, és ebből nem lehet kár.
// Re-sending the same index overwrites the part, so a retry is idempotent.
$request->file('chunk')->move($dir, sprintf('%06d.part', $index));
// ... later, in complete(): assemble the parts in order
$out = fopen($assembled, 'wb');
for ($i = 0; $i < $info['total_chunks']; $i++) {
$part = $dir.'/'.sprintf('%06d.part', $i);
if (! is_file($part)) {
fclose($out);
return response()->json(['success' => false, 'message' => "Missing chunk: {$i}"], 422);
}
$in = fopen($part, 'rb');
stream_copy_to_stream($in, $out);
fclose($in);
}
fclose($out);
if (filesize($assembled) !== $info['size']) {
File::deleteDirectory($dir);
return response()->json(['success' => false, 'message' => 'Size mismatch.'], 422);
}
Kivonat valódi kódból, anonimizálva.
Amit még érdemes tudni
A méretet és a típust az összefűzött fájlon ellenőrzöm, nem azon, amit a kliens állít, mert az utóbbi hamisítható. A futtatható és szerveroldali kiterjesztéseket letiltom. Az összefűzés után a darabok mappája törlődik.
Az egykérésű feltöltő végpontot meghagytam visszafelé kompatibilitás miatt, de az új oldalak már nem használják.
Hasonló problémán dolgozol?
Ha elakadtál, vagy átnéztetnéd a megoldásodat, írj, szívesen megnézem.
Írok neked →További cikkek
Legacy rendszer újraírása működés közben
Hogyan cserélek le egy régi rendszert úgy, hogy a felhasználók közben dolgozhatnak: azonos viselkedés, eltérések listája, naplózás.
Elolvasom →Hogyan ne küldj rossz levelet rossz embernek
Az e-mail kampányoknál a küldés a könnyű rész. Ezek azok a védelmi rétegek, amiket a saját rendszerembe építettem.
Elolvasom →