burzum / cakephp-file-storage

Abstract file storage and upload plugin for CakePHP. Write to local disk, FTP, S3, Dropbox and more through a single interface. It's not just yet another uploader but a complete storage solution.
MIT License
197 stars 84 forks source link

Created a script to upload files to S3 - files uploaded but script throws error The listener `Burzum\FileStorage\Storage\Listener\LocalListener` doesn't allow the `\Gaufrette\Adapter\AwsS3` adapter class! Probably because it can't work with it #202

Closed nuzulfikrie closed 4 years ago

nuzulfikrie commented 4 years ago

Hi All,

I followed the documentations that is listed here from https://cakephp-file-storage.readthedocs.io/en/latest/Tutorials/Quick-Start/.

When I followed this, and run from console. The script throws The listener Burzum\FileStorage\Storage\Listener\LocalListener doesn't allow the \Gaufrette\Adapter\AwsS3 adapter class! Probably because it can't work with it.


use Aws\S3\S3Client;
use Burzum\FileStorage\Storage\Listener\BaseListener;
use Burzum\FileStorage\Storage\StorageUtils;
use Burzum\FileStorage\Storage\StorageManager;
use Cake\Core\Configure;
use Cake\Event\EventManager;

// Instantiate a storage event listener
$listener = new BaseListener(
    'imageProcessing' => true, // Required if you want image processing!
    'pathBuilderOptions' => [
        // Preserves the original filename in the storage backend.
        // Otherwise it would use a UUID as filename by default.
        'preserveFilename' => true
    ]
);
// Attach the BaseListener to the global EventManager
EventManager::instance()->on($listener);

Configure::write('FileStorage', [
// Configure image versions on a per model base
    'imageSizes' => [
        'ProductImage' => [
            'large' => [
                'thumbnail' => [
                    'mode' => 'inbound',
                    'width' => 800,
                    'height' => 800
                ]
            ],
            'medium' => [
                'thumbnail' => [
                    'mode' => 'inbound',
                    'width' => 200,
                    'height' => 200
                ]
            ],
            'small' => [
                'thumbnail' => [
                    'mode' => 'inbound',
                    'width' => 80,
                    'height' => 80
                ]
            ]
        ]
    ]
]);

// This is very important! The hashes are needed to calculate the image versions!
StorageUtils::generateHashes();

// Lets use the Amazon S3 adapter here instead of the default `Local` config.
// We need to pass a S3Client instance to this adapter to make it work
$S3Client = new S3Client([
    'version' => 'latest',
    'region'  => 'eu-central-1',
    'credentials' => [
        'key' => 'YOUR-AWS-S3-KEY-HERE',
        'secret' => 'YOUR-SECRET-HERE'
    ]
]);

// Configure the S3 adapter instance through the StorageManager
StorageManager::config('S3', [
    'adapterOptions' => array(
        $S3Client,
        'YOUR-BUCKET-NAME-HERE', // Bucket
        [],
        true
    ),
    'adapterClass' => '\Gaufrette\Adapter\AwsS3',
    'class' => '\Gaufrette\Filesystem'
]);
nuzulfikrie commented 4 years ago

I put Adapter class 'adapterClass' => '\Gaufrette\Adapter\AwsS3', in LocalListener.php and the script work. Is it the intended design?


    public $_adapterClasses = [
        '\Gaufrette\Adapter\Local',
        '\Gaufrette\Adapter\AwsS3'
    ];
burzum commented 4 years ago

@nuzulfikrie this is intended, but it is not intended that you change this class. If it works you're lucky because the adapters API is compatible. But there might be things that break. A LOCAL adapter is for a reason a LOCAL adapter. It will very likely behave different than one for a cloud based storage. The listeners expect specific adapters because of that. They don't assume that a LOCAL adapter behaves the same as the cloud adapter. Again: If it works you're lucky, if you run into issues with this listener using a CLOUD adapter you know why. :)

nuzulfikrie commented 4 years ago

@nuzulfikrie this is intended, but it is not intended that you change this class. If it works you're lucky because the adapters API is compatible. But there might be things that break. A LOCAL adapter is for a reason a LOCAL adapter. It will very likely behave different than one for a cloud based storage. The listeners expect specific adapters because of that. They don't assume that a LOCAL adapter behaves the same as the cloud adapter. Again: If it works you're lucky, if you run into issues with this listener using a CLOUD adapter you know why. :)

Thanks @burzum . I am still hoping ( and working ) to use this plugin. A very good one.

burzum commented 4 years ago

@nuzulfikrie well, just implement your own listener for AWS. You can test if LocalListener works fine, if not figure out the difference and create your own listener based on that one.

In theory all the adapters could or should even work. The underlying library Gaufrette should abstract that very well but no guarantee given.

So yes, you can extend the Listener in your app and just override the $_adapterClasses property in it and add the adapter if it works for you.