Dynamically change the storageLocation during upload

I use an aws S3 file storage location as my default for image files. Works great.

When uploading videos I need to change this storage location to another AWS file storage location that I have installed. I can set this location as the default and it works fine.

I need to dynamically switch from the AWS location for images to the one for videos when needed. Past efforts:
1). At first I thought my solution was to ‘setStorageLocation’ but now I think not as that will persist a system wide change(?).
2). I see that ‘setFileStorageLocation’ is for moving an existing file from one location to another. I would prefer to not do double duty and go directly to the AWS S3 bucket.

On 8.5 I see that the Concrete/Core/File/Importer.php is being deprecated but that’s what I’m using right now. The Importer->import() shows the 3rd param can be a file resource. This would seem a runtime decision changing the location and that seems best:
1). I can get the (installed) storage location I want with:

    $app = \Concrete\Core\Support\Facade\Application::getFacadeApplication();
    $my_aws_s3_videos_storage = $app[FileStorageLocationFactory::class]->fetchByName('my_aws_s3_videos');

QUESTION: How do I turn that into a file resource I can pass as the 3rd param in Importer->import() ??

If I can get the $my_aws_s3_videos_storage as a FileEntity then the Importer->import will call the getFileStorageLocationObject() on that 3rd param and then all should be good.

Thoughts/Suggestions? Thanks!

I assume you’ve checked for some ideas in the file storage location documentation. Since you are changing things based on the type of filetype, file processors information at the bottom if this page may help: File Storage Locations

Thanks for the reply, Myq, sorry for the delayed response.

As the code I posted demonstrates, a storage location is set and the file type recognition is determined - but there seems no way to dynamically change the $my_aws_s3_videos_storage object into a FileEntity for it to be used as the 3rd parameter in the Importer->import() method which would appear to send the upload to the intended storage location (and not require it to be MOVED later).

For now, I am using the (previously mentioned) ‘setFileStorageLocation’ method to MOVE the uploaded file that went to the default directory back over to the intended storage location ($my_aws_s3_videos_storage). Seems a bit needless to do it that way - perhaps I’m missing something simple.

It appears the C5 Core team is deprecating the Importer class for the 9 release. Maybe they would like to know about this use-case scenario (if in fact it has not been addressed)?

Has the slack.concrete5.org been taken down or just moved? You were actively supporting developers there for a while.

BTW, nice work on the concretecms.org site. Looks good!

Considering the process:

  1. Browser uploads file to server
  2. Server saves file in temporary location
  3. php provides path to temporary location in $_FILES
  4. request object provides abstracted interface to file
  5. In c5, file is copied or moved to file manager storage location concrete/src/File/Import/FileImporter.php
  6. Various thumbnails are created

Unless (1) is circumvented to send the file from the browser directly to S3, I doubt if there is any big efficiency improvement available by modifying step (5). The process will always involve a copy from a server local file to S3.

With that in mind, perhaps a simpler solution is to upload to a local storage location and then handle an event Full Event List :: Concrete CMS

Then from the event handler change the file storage location to the appropriate S3 location after it has been uploaded and thumbnailed.

An alternative to handling an event may be to add a pre or post processor to adjust the storage location.

This may actually be more efficient if thumbnail generation is done locally without to and from S3.

(This is not something I have implemented, so could just be my flakey thinking. There are several events to experiment with)

C5 enables a nice Storage Location interface to set the default to be an S3 bucket. i retrofitted this package to make my modifications work: https://github.com/torsoe/concrete5_amazon_s3_filemanager. There appears a more robust solution in the marketplace https://marketplace.concretecms.com/marketplace/addons/storage-for-amazon-s3 but I didn’t need it for my use case.

Your step 1 is never circumvented, it happens in step 5. If an S3 storage location is set as default then c5 just does what it does using the Flysystem/Filesystem s3 Adapter built into the package.

The C5 ‘setFileStorageLocation’ method is clearly documented as ‘moving’ the file from it’s default location to a new ‘fileStorageLocation’. It works, and it (the move-step) gives me a chance to change the file prefix (no slashes) which is needed when dealing with AWS’s MediaConvert api for streaming video. So, I’m good, but I just thought I could be doing it better.

I think my bold-typed question (above) is asking the right question, because the C5 system seems built to handle a ‘dynamic change’ of the file storage location if I could only convert the secondary S3 storage location object ($my_aws_s3_videos_storage) into a FileEntity so it can be passed as the 3rd param in the import method because that code seems like it would handle the storage location change on the fly and eliminate the need for a second move operation.

The move op is working, but I thought I was missing something simple and already built by C5.