mirror of
https://github.com/HDInnovations/UNIT3D.git
synced 2026-01-31 01:35:31 +01:00
refactor: create zips in-memory instead of on filesystem
Co-Authored-By: Roardom <78790963+Roardom@users.noreply.github.com>
This commit is contained in:
@@ -20,7 +20,7 @@ use App\Helpers\Bencode;
|
||||
use App\Models\Playlist;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipArchive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
/**
|
||||
* @see \Tests\Todo\Feature\Http\Controllers\PlaylistControllerTest
|
||||
@@ -30,7 +30,7 @@ class PlaylistZipController extends Controller
|
||||
/**
|
||||
* Download All Playlist Torrents.
|
||||
*/
|
||||
public function show(Playlist $playlist): \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
public function show(Playlist $playlist): \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
// Extend The Maximum Execution Time
|
||||
set_time_limit(300);
|
||||
@@ -41,50 +41,40 @@ class PlaylistZipController extends Controller
|
||||
// Authorized User
|
||||
$user = auth()->user();
|
||||
|
||||
// Define Dir Folder
|
||||
$path = Storage::disk('temporary-zips')->path('');
|
||||
|
||||
// Check Directory exists
|
||||
if (!File::isDirectory($path)) {
|
||||
File::makeDirectory($path, 0755, true, true);
|
||||
}
|
||||
|
||||
// Zip File Name
|
||||
$zipFileName = '['.$user->username.']'.$playlist->name.'.zip';
|
||||
|
||||
// Create ZipArchive Obj
|
||||
$zipArchive = new ZipArchive();
|
||||
return response()->streamDownload(
|
||||
function () use ($zipFileName, $user, $playlist): void {
|
||||
$zip = new ZipStream(outputName: sanitize_filename($zipFileName));
|
||||
|
||||
if ($zipArchive->open($path.$zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
||||
$announceUrl = route('announce', ['passkey' => $user->passkey]);
|
||||
$announceUrl = route('announce', ['passkey' => $user->passkey]);
|
||||
|
||||
foreach ($playlist->torrents()->get() as $torrent) {
|
||||
$dict = Bencode::bdecode(Storage::disk('torrent-files')->get($torrent->file_name));
|
||||
foreach ($playlist->torrents()->get() as $torrent) {
|
||||
if (Storage::disk('torrent-files')->exists($torrent->file_name)) {
|
||||
$dict = Bencode::bdecode(Storage::disk('torrent-files')->get($torrent->file_name));
|
||||
|
||||
// Set the announce key and add the user passkey
|
||||
$dict['announce'] = $announceUrl;
|
||||
// Set the announce key and add the user passkey
|
||||
$dict['announce'] = $announceUrl;
|
||||
|
||||
// Set link to torrent as the comment
|
||||
if (config('torrent.comment')) {
|
||||
$dict['comment'] = config('torrent.comment').'. '.route('torrents.show', ['id' => $torrent->id]);
|
||||
} else {
|
||||
$dict['comment'] = route('torrents.show', ['id' => $torrent->id]);
|
||||
// Set link to torrent as the comment
|
||||
if (config('torrent.comment')) {
|
||||
$dict['comment'] = config('torrent.comment').'. '.route('torrents.show', ['id' => $torrent->id]);
|
||||
} else {
|
||||
$dict['comment'] = route('torrents.show', ['id' => $torrent->id]);
|
||||
}
|
||||
|
||||
$fileToDownload = Bencode::bencode($dict);
|
||||
|
||||
$filename = sanitize_filename('['.config('torrent.source').']'.$torrent->name.'.torrent');
|
||||
|
||||
$zip->addFile($filename, $fileToDownload);
|
||||
}
|
||||
}
|
||||
|
||||
$fileToDownload = Bencode::bencode($dict);
|
||||
|
||||
$filename = str_replace([' ', '/', '\\'], ['.', '-', '-'], '['.config('torrent.source').']'.$torrent->name.'.torrent');
|
||||
|
||||
$zipArchive->addFromString($filename, $fileToDownload);
|
||||
}
|
||||
|
||||
$zipArchive->close();
|
||||
}
|
||||
|
||||
if (Storage::disk('temporary-zips')->exists($zipFileName)) {
|
||||
return response()->download(Storage::disk('temporary-zips')->path($zipFileName))->deleteFileAfterSend(true);
|
||||
}
|
||||
|
||||
return redirect()->back()->withErrors(trans('common.something-went-wrong'));
|
||||
$zip->finish();
|
||||
},
|
||||
sanitize_filename($zipFileName),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipArchive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class TorrentZipController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show zip file containing all torrents user has history of.
|
||||
*/
|
||||
public function show(Request $request, User $user): \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
public function show(Request $request, User $user): \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
// Extend The Maximum Execution Time
|
||||
set_time_limit(1200);
|
||||
@@ -59,52 +59,38 @@ class TorrentZipController extends Controller
|
||||
return redirect()->back()->withErrors('No Torrents Found');
|
||||
}
|
||||
|
||||
// Define Dir For Zip
|
||||
$zipPath = Storage::disk('temporary-zips')->path('');
|
||||
return response()->streamDownload(
|
||||
function () use ($zipFileName, $user, $torrents): void {
|
||||
$zip = new ZipStream(outputName: sanitize_filename($zipFileName));
|
||||
|
||||
// Check Directory exists
|
||||
if (!File::isDirectory($zipPath)) {
|
||||
File::makeDirectory($zipPath, 0755, true, true);
|
||||
}
|
||||
$announceUrl = route('announce', ['passkey' => $user->passkey]);
|
||||
|
||||
// Create ZipArchive Obj
|
||||
$zipArchive = new ZipArchive();
|
||||
foreach ($torrents as $torrent) {
|
||||
if (Storage::disk('torrent-files')->exists($torrent->file_name)) {
|
||||
$dict = Bencode::bdecode(Storage::disk('torrent-files')->get($torrent->file_name));
|
||||
|
||||
if ($zipArchive->open($zipPath.$zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
||||
$announceUrl = route('announce', ['passkey' => $user->passkey]);
|
||||
// Set the announce key and add the user passkey
|
||||
$dict['announce'] = $announceUrl;
|
||||
|
||||
foreach ($torrents as $torrent) {
|
||||
if (Storage::disk('torrent-files')->exists($torrent->file_name)) {
|
||||
$dict = Bencode::bdecode(Storage::disk('torrent-files')->get($torrent->file_name));
|
||||
// Set link to torrent as the comment
|
||||
if (config('torrent.comment')) {
|
||||
$dict['comment'] = config('torrent.comment').'. '.route('torrents.show', ['id' => $torrent->id]);
|
||||
} else {
|
||||
$dict['comment'] = route('torrents.show', ['id' => $torrent->id]);
|
||||
}
|
||||
|
||||
// Set the announce key and add the user passkey
|
||||
$dict['announce'] = $announceUrl;
|
||||
$fileToDownload = Bencode::bencode($dict);
|
||||
|
||||
// Set link to torrent as the comment
|
||||
if (config('torrent.comment')) {
|
||||
$dict['comment'] = config('torrent.comment').'. '.route('torrents.show', ['id' => $torrent->id]);
|
||||
} else {
|
||||
$dict['comment'] = route('torrents.show', ['id' => $torrent->id]);
|
||||
$filename = sanitize_filename('['.config('torrent.source').']'.$torrent->name.'.torrent');
|
||||
|
||||
$zip->addFile($filename, $fileToDownload);
|
||||
}
|
||||
|
||||
$fileToDownload = Bencode::bencode($dict);
|
||||
|
||||
$filename = str_replace(
|
||||
[' ', '/', '\\'],
|
||||
['.', '-', '-'],
|
||||
'['.config('torrent.source').']'.$torrent->name.'.torrent'
|
||||
);
|
||||
|
||||
$zipArchive->addFromString($filename, $fileToDownload);
|
||||
}
|
||||
}
|
||||
|
||||
$zipArchive->close();
|
||||
}
|
||||
|
||||
if (Storage::disk('temporary-zips')->exists($zipFileName)) {
|
||||
return response()->download(Storage::disk('temporary-zips')->path($zipFileName))->deleteFileAfterSend(true);
|
||||
}
|
||||
$zip->finish();
|
||||
},
|
||||
sanitize_filename($zipFileName),
|
||||
);
|
||||
|
||||
return redirect()->back()->withErrors(trans('common.something-went-wrong'));
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"laravel/scout": "^10.15.0",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"livewire/livewire": "^3.6.3",
|
||||
"maennchen/zipstream-php": "^3.1",
|
||||
"marcreichel/igdb-laravel": "^5.3.1",
|
||||
"meilisearch/meilisearch-php": "^1.15.0",
|
||||
"paragonie/constant_time_encoding": "^2.7.0",
|
||||
|
||||
80
composer.lock
generated
80
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1f9f75b35bc72983c2376de766559b45",
|
||||
"content-hash": "fbf86c3569b76d46d0eded20d7b15a9f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "assada/laravel-achievements",
|
||||
@@ -3419,6 +3419,84 @@
|
||||
],
|
||||
"time": "2025-04-12T22:26:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maennchen/zipstream-php",
|
||||
"version": "3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"ext-zlib": "*",
|
||||
"php-64bit": "^8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^7.7",
|
||||
"ext-zip": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.16",
|
||||
"guzzlehttp/guzzle": "^7.5",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"php-coveralls/php-coveralls": "^2.5",
|
||||
"phpunit/phpunit": "^11.0",
|
||||
"vimeo/psalm": "^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"guzzlehttp/psr7": "^2.4",
|
||||
"psr/http-message": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ZipStream\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paul Duncan",
|
||||
"email": "pabs@pablotron.org"
|
||||
},
|
||||
{
|
||||
"name": "Jonatan Männchen",
|
||||
"email": "jonatan@maennchen.ch"
|
||||
},
|
||||
{
|
||||
"name": "Jesse Donat",
|
||||
"email": "donatj@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "András Kolesár",
|
||||
"email": "kolesar@kolesar.hu"
|
||||
}
|
||||
],
|
||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
||||
"keywords": [
|
||||
"stream",
|
||||
"zip"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/maennchen",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-27T12:07:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "marcreichel/igdb-laravel",
|
||||
"version": "5.3.1",
|
||||
|
||||
@@ -127,11 +127,6 @@ return [
|
||||
'root' => storage_path('app/files/subtitles/files'),
|
||||
],
|
||||
|
||||
'temporary-zips' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/tmp/zips'),
|
||||
],
|
||||
|
||||
'temporary-nfos' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/tmp/nfos'),
|
||||
|
||||
Reference in New Issue
Block a user