dbp/relay-blob-connector-filesystem-bundle
Prerequisites:
dbp/relay-blob-bundle (parent package) via Composer:
composer require dbp/relay-blob-bundle
DbpRelayCoreBundle is installed (required by the parent bundle).Install the Filesystem Connector:
composer require dbp/relay-blob-connector-filesystem-bundle
Register the Bundle:
Add to config/bundles.php before DbpRelayBlobBundle:
Dbp\Relay\BlobBundle\DbpRelayBlobConnectorFilesystemBundle::class => ['all' => true],
Configure Storage Path:
Publish the default config and update config/packages/dbp_relay_blob.yaml:
dbp_relay_blob:
datasystems:
filesystem:
connector: filesystem
options:
path: '%kernel.project_dir%/var/blobs' # Customize path
First Use Case:
Upload a blob via the Relay API (e.g., using multipart/form-data):
curl -X POST -F "file=@/path/to/file.jpg" http://your-app/_relay/blob
Verify the file exists at the configured path.
Blob Storage:
path./var/blobs/
├── {uuid}/
│ ├── original_filename.ext
│ └── ... (metadata files if added later)
Integration with Relay API:
/_relay/blob) for all blob operations.# Upload
curl -X POST -F "file=@image.png" http://app/_relay/blob
# Get share link (temporary)
curl -X POST http://app/_relay/blob/share --data '{"blobId":"uuid-here"}'
# Delete
curl -X DELETE http://app/_relay/blob --data '{"blobId":"uuid-here"}'
Symfony Service Integration:
use Dbp\Relay\BlobBundle\Service\DatasystemProviderServiceInterface;
class MyService {
public function __construct(
private DatasystemProviderServiceInterface $filesystemProvider
) {}
public function storeFile($file) {
$blob = $this->filesystemProvider->store($file, 'filesystem');
return $blob->getId();
}
}
Customizing Storage:
path in config or dynamically via environment variables:
options:
path: '%env(RELAY_BLOB_PATH)%'
Share Links:
Multi-Datasystem Setup:
Combine with other connectors (e.g., S3) in config/packages/dbp_relay_blob.yaml:
datasystems:
filesystem:
connector: filesystem
options: { path: '%kernel.project_dir%/var/blobs' }
s3:
connector: aws_s3
options: { ... }
Event Listeners:
Hook into blob events (e.g., BlobStoredEvent) to trigger post-upload actions:
use Dbp\Relay\BlobBundle\Event\BlobStoredEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class BlobSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
BlobStoredEvent::class => 'onBlobStored',
];
}
public function onBlobStored(BlobStoredEvent $event) {
// Custom logic (e.g., log, notify, transform)
}
}
Testing:
use Symfony\Component\Filesystem\Filesystem;
$fs = new Filesystem();
$fs->mkdir(sys_get_temp_dir().'/relay_blob_tests');
$this->container->setParameter('kernel.project_dir', sys_get_temp_dir());
Bundle Loading Order:
DbpRelayBlobConnectorFilesystemBundle before DbpRelayBlobBundle in config/bundles.php.DatasystemProviderServiceInterface not being registered.Path Permissions:
path is writable by the web server user (e.g., www-data).chmod -R 775 %kernel.project_dir%/var/blobs
Share Link Expiry:
UUID Collisions:
Missing Changelog:
git log --oneline --grep="fix\|feat" https://github.com/digital-blueprint/relay-blob-connector-filesystem-bundle.git
Enable Relay Debug Mode:
Add to .env:
RELAY_DEBUG=true
Logs blob operations to var/log/dev.log.
Check Stored Files: Verify files exist at the configured path:
ls -la %kernel.project_dir%/var/blobs/
API Response Errors:
Content-Type).var/log/dev.log for filesystem permission issues.Dependency Conflicts:
relay-blob-bundle and this connector are on compatible versions (check composer.json constraints).Custom Connector Class: Extend the default filesystem connector to add features (e.g., custom share link expiry):
namespace App\Relay\Blob;
use Dbp\Relay\BlobBundle\Connector\FilesystemConnector;
use Dbp\Relay\BlobBundle\Model\Blob;
class CustomFilesystemConnector extends FilesystemConnector {
protected function generateShareLink(Blob $blob): string {
return parent::generateShareLink($blob) . '?expires=' . time() + 86400; // 24h expiry
}
}
Register in config/services.yaml:
services:
Dbp\Relay\BlobBundle\Service\DatasystemProviderServiceInterface.filesystem:
class: App\Relay\Blob\CustomFilesystemConnector
arguments: ['@filesystem']
Add Metadata Files:
Store additional metadata (e.g., blob.json) alongside files:
use Symfony\Component\Filesystem\Filesystem;
class MySubscriber implements EventSubscriberInterface {
public function onBlobStored(BlobStoredEvent $event) {
$fs = new Filesystem();
$metadata = [
'uploaded_at' => (new \DateTime())->format('c'),
'user_id' => 123,
];
$fs->dumpFile(
$event->getBlob()->getPath().'/metadata.json',
json_encode($metadata)
);
}
}
Override Default Config:
Use config/packages/override/dbp_relay_blob.yaml to avoid merging conflicts:
dbp_relay_blob:
datasystems:
filesystem:
options:
path: '/custom/path'
umask: 0002 # Set file permissions
Disable File Locking: If using a high-traffic system, disable file locking in the connector (requires custom class):
protected function storeFile($file, $path) {
file_put_contents($path, file_get_contents($file->getPathname()));
// Skip flock() calls
}
Use symlink for Large Files:
For very large files, store the file elsewhere and symlink it to the blob directory:
$fs->symlink('/large/files/'.$file->getClientOriginalName(), $path);
Cache Share Links: Cache generated share links in Redis or APCu to reduce filesystem checks:
$cache = $this->container->get('cache.app');
$cache->set('blob_share_'.$blob->getId(), $shareLink, 3
How can I help you explore Laravel packages today?