filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
19.08k stars 2.94k forks source link

Prebuilt Import action does not support s3 FILESYSTEM_DISK #10081

Closed GerhardKotze closed 11 months ago

GerhardKotze commented 11 months ago

Package

filament/actions

Package Version

v3.1.8

Laravel Version

v10.10

Livewire Version

v3.0.8

PHP Version

PHP 8.1.24

Problem description

CSV file import on Import Action gives 500 error when using s3 as storage. I can confirm file is uploaded to s3 in livewire-tmp/ directory. Logs show that /var/task/vendor/filament/actions/src/Concerns/CanImportRecords tried fopen(livewire-tmp/CkWtDN6ab0XILQOXGrfMxyJ8cz8Bnl-metacHJvZHVjdC1pbXBvcnRlci1leGFtcGxlLmNzdg==-.csv) and failed to find the file/directory.

Expected behavior

File uploaded successfully into S3 and import of rows started from file saved in s3.

Steps to reproduce

  1. Set environment FILESYSTEM_DISK=s3 FILESYSTEM_DISK=s3

  2. Add your s3 details to environment.

  3. Create importer.

namespace App\Filament\Imports;

use App\Models\Product;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;

class ProductImporter extends Importer
{
    protected static ?string $model = Product::class;

    public static function getColumns(): array
    {
        return [
            ImportColumn::make('id')
                ->label('Unique Product Id')
                ->requiredMapping()
                ->rules(['required', 'max:255'])
                ->guess(['id', 'supplier_reference']),
            ImportColumn::make('name')
                ->requiredMapping()
                ->rules(['required', 'max:255']),
            ImportColumn::make('description')
                ->rules(['max:255']),
        ];
    }

    public function resolveRecord(): ?Product
    {
        return Product::firstOrNew([
            // Update existing records, matching them by `$this->data['column_name']`
            'supplier_id' => $this->data['id'],
        ]);

        return new Product();
    }

    public static function getCompletedNotificationBody(Import $import): string
    {
        $body = 'Your product import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';

        if ($failedRowsCount = $import->getFailedRowsCount()) {
            $body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
        }

        return $body;
    }
} 
  1. Add importer to Resource.

    ->headerActions([ ImportAction::make() ->importer(ProductImporter::class) ->maxRows(100000), Tables\Actions\CreateAction::make(), ])

  2. Upload file via importer.

Reproduction repository

https://github.com/GerhardKotze/fuzzy-pancake

Relevant log output

{
"userId": 
3,
"exception": 
{
"class": 
"ErrorException",
"message": 
"fopen(livewire-tmp/CkWtDN6ab0XILQOXGrfMxyJ8cz8Bnl-metacHJvZHVjdC1pbXBvcnRlci1leGFtcGxlLmNzdg==-.csv): Failed to open stream: No such file or directory",
"code": 
0,
"file": 
"/var/task/vendor/filament/actions/src/Concerns/CanImportRecords.php:311"
},
"aws_request_id": 
"d9876be9-e0fa-404e-b684-32a7bca15cbf"
}
danharrin commented 11 months ago

I built this feature specifically on top of S3. What is FILAMENT_FILESYSTEM_DISK set to?

GerhardKotze commented 11 months ago

Hi Dan, Apologies for wasting your time. I only set FILESYSTEM_DISK and not FILAMENT_FILESYSTEM_DISK. I assumed issue was unrelated as file was indeed uploaded to S3 when checking the bucket. Setting FILAMENT_FILESYSTEM_DISK=s3 resolved my issue.

filipe-dynamics commented 8 months ago

Hi @GerhardKotze, Ask me a question, if possible. Are you using Amazon's AWS S3? I have the same problem as you, but I'm using Digital Ocean's S3. Your problem is exactly the same as mine, and I did everything you did, but the error still persisted.

rikoriswandha commented 7 months ago

@filipe-dynamics did you resolve that issue?

leoblanski commented 6 months ago

Same problem here.

If I remove FILAMENT_FILESYSTEM_DISK it works, but when setting, it returns s3 error when trying to import.

kyagie commented 3 months ago

@danharrin Anyone got a solution this problem?

I'm using Digital Ocean's S3 object storage?

My FILAMENT_FILESYSTEM_DISK is to s3

s3 => [ 'driver' => 's3', 'key' => env('DO_SPACES_KEY'), 'secret' => env('DO_SPACES_SECRET'), 'region' => env('DO_SPACES_REGION'), 'bucket' => env('DO_SPACES_BUCKET'), 'url' => env('DO_SPACES_URL'), 'endpoint' => env('DO_SPACES_ENDPOINT'), 'use_path_style_endpoint' => env('DO_SPACES_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, ],

tygoegmond commented 2 months ago

If you use DigitalOcean you need to ensure that you add the following "Allowed Headers" to your CORS settings:

@kyagie, @leoblanski, @rikoriswandha, @filipe-dynamics

kyagie commented 2 months ago

If you use DigitalOcean you need to ensure that you add the following "Allowed Headers" to your CORS settings:

  • Content-Type

  • X-Amz-Acl

@kyagie, @leoblanski, @rikoriswandha, @filipe-dynamics

Yes, I fixed this.