Skip to content

Commit f8bb31f

Browse files
committed
upload images to nova
1 parent 8518713 commit f8bb31f

3 files changed

Lines changed: 133 additions & 18 deletions

File tree

app/Nova/Actions/BulkUploadMediaFiles.php

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
namespace App\Nova\Actions;
44

55
use App\MediaUpload;
6+
use DigitalCreative\Filepond\Filepond;
7+
use DigitalCreative\Filepond\Data\Data;
68
use Illuminate\Bus\Queueable;
79
use Illuminate\Http\UploadedFile;
810
use Illuminate\Queue\InteractsWithQueue;
911
use Illuminate\Queue\SerializesModels;
1012
use Illuminate\Support\Collection;
13+
use Illuminate\Support\Facades\Storage;
1114
use Illuminate\Support\Str;
1215
use Laravel\Nova\Actions\Action;
1316
use Laravel\Nova\Fields\ActionFields;
14-
use Laravel\Nova\Fields\File;
1517
use Laravel\Nova\Http\Requests\NovaRequest;
1618

1719
class BulkUploadMediaFiles extends Action
@@ -53,20 +55,22 @@ public function handle(ActionFields $fields, Collection $models)
5355
continue;
5456
}
5557

56-
$extension = strtolower((string) $file->getClientOriginalExtension());
58+
$originalName = $this->extractOriginalName($file);
59+
if ($originalName === null) {
60+
$skipped++;
61+
continue;
62+
}
63+
$extension = strtolower((string) pathinfo($originalName, PATHINFO_EXTENSION));
5764
if (!in_array($extension, $allowedExtensions, true)) {
5865
$skipped++;
5966
continue;
6067
}
6168

62-
$baseName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
69+
$baseName = pathinfo($originalName, PATHINFO_FILENAME);
6370
$safeBaseName = Str::slug($baseName) ?: 'upload-file';
6471
$destination = 'nova/uploads/' . now()->format('Y/m');
65-
$storedPath = $file->storeAs(
66-
$destination,
67-
$safeBaseName . '-' . Str::random(8) . '.' . $extension,
68-
'resources'
69-
);
72+
$finalFileName = $safeBaseName . '-' . Str::random(8) . '.' . $extension;
73+
$storedPath = $this->storeFile($file, $destination, $finalFileName);
7074

7175
if (!$storedPath) {
7276
$skipped++;
@@ -94,14 +98,10 @@ public function handle(ActionFields $fields, Collection $models)
9498
public function fields(NovaRequest $request): array
9599
{
96100
return [
97-
File::make('Files', 'files')
98-
->withMeta([
99-
'extraAttributes' => [
100-
'name' => 'files[]',
101-
'multiple' => true,
102-
'accept' => '.jpg,.jpeg,.png,.gif,.webp,.svg,.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.txt',
103-
],
104-
])
101+
Filepond::make('Files', 'files')
102+
->multiple()
103+
->limit(50)
104+
->acceptedTypes('.jpg,.jpeg,.png,.gif,.webp,.svg,.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.txt')
105105
->rules('required')
106106
->help('Drag and drop multiple files or click to select. Supported: images, PDF, Office docs, and TXT.'),
107107
];
@@ -120,6 +120,11 @@ protected function collectUploadedFiles(ActionFields $fields): array
120120
$candidates[] = $fields->files;
121121
}
122122

123+
$requestItems = request()->collect('files')->all();
124+
if (!empty($requestItems)) {
125+
$candidates[] = $requestItems;
126+
}
127+
123128
$requestFiles = request()->allFiles();
124129
if (!empty($requestFiles)) {
125130
$candidates[] = $requestFiles;
@@ -130,6 +135,10 @@ protected function collectUploadedFiles(ActionFields $fields): array
130135
return [$value];
131136
}
132137

138+
if (is_string($value)) {
139+
return [$value];
140+
}
141+
133142
if (!is_array($value)) {
134143
return [];
135144
}
@@ -150,4 +159,47 @@ protected function collectUploadedFiles(ActionFields $fields): array
150159
return $files;
151160
}
152161

162+
protected function extractOriginalName(UploadedFile|string $file): ?string
163+
{
164+
if ($file instanceof UploadedFile) {
165+
return $file->getClientOriginalName();
166+
}
167+
168+
try {
169+
$data = Data::fromEncrypted($file);
170+
return $data->filename;
171+
} catch (\Throwable $e) {
172+
return null;
173+
}
174+
}
175+
176+
protected function storeFile(UploadedFile|string $file, string $destination, string $finalFileName): ?string
177+
{
178+
if ($file instanceof UploadedFile) {
179+
return $file->storeAs($destination, $finalFileName, 'resources');
180+
}
181+
182+
try {
183+
$data = Data::fromEncrypted($file);
184+
} catch (\Throwable $e) {
185+
return null;
186+
}
187+
188+
$stream = Storage::disk($data->disk)->readStream($data->path);
189+
if ($stream === false) {
190+
return null;
191+
}
192+
193+
$targetPath = $destination . '/' . $finalFileName;
194+
$stored = Storage::disk('resources')->put($targetPath, $stream, 'public');
195+
if (is_resource($stream)) {
196+
fclose($stream);
197+
}
198+
199+
// Clean temporary Filepond directory.
200+
$data->deleteDirectory();
201+
202+
return $stored ? $targetPath : null;
203+
}
204+
153205
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"ext-zip": "*",
1414
"aws/aws-sdk-php": "^3.131",
1515
"ctessier/nova-advanced-image-field": "^2.1",
16+
"digital-creative/nova-filepond": "^1.0",
1617
"doctrine/dbal": "^3.5",
1718
"guzzlehttp/guzzle": "^7.2",
1819
"intervention/image": "^2.7",

composer.lock

Lines changed: 64 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)