avtonom/media-storage-client-bundle
Installation
composer require avtonom/media-storage-client-bundle:~1.2
Replace ~1.2 with the latest stable version.
Register the Bundle
Add to config/bundles.php (Symfony 4+) or app/AppKernel.php (Symfony 3):
return [
// ...
Avtonom\MediaStorageClientBundle\AvtonomMediaStorageClientBundle::class => ['all' => true],
Sensio\Bundle\BuzzBundle\SensioBuzzBundle::class => ['all' => true],
];
Basic Configuration
Define remote storage endpoints in config/packages/avtonom_media_storage_client.yaml:
avtonom_media_storage_client:
clients:
sonata_media_client:
base_url: "https://your-sonata-media-server.com"
add_media_url: "/api/media/upload"
urls:
get_media_by_reference_full_url: "/api/media/referencefull"
First Use Case Upload a file via a controller:
use Symfony\Component\HttpFoundation\File\UploadedFile;
public function uploadFile(UploadedFile $file)
{
$proxyMedia = $this->get('avtonom.media_storage_client.manager')
->sendFile($file, 'sonata_media_client', 'default_context');
return new JsonResponse(['media' => $proxyMedia->toArray()]);
}
File Upload via API
sendFile() method in controllers or services:
$proxyMedia = $this->mediaStorageClient->sendFile(
$uploadedFile,
'client_name_from_config',
'optional_context'
);
mediaReferenceFull in your entity).Entity Listeners for Automatic Uploads
services:
avtonom.media_storage_client.listener:
class: Avtonom\MediaStorageClientBundle\EventListener\ObjectAddFileListener
arguments:
- '@avtonom.media_storage_client.manager'
- '%avtonom.media_storage_client.listener%'
tags:
- { name: doctrine.event_listener, event: prePersist, method: run }
- { name: doctrine.event_listener, event: preUpdate, method: run }
config/packages/avtonom_media_storage_client.yaml:
listener:
interfaces: ['App\Entity\Product', 'App\Entity\Article']
change_field: 'imageFile' # Field to trigger upload
client: 'sonata_media_client'
Frontend Integration
{% include '@AvtonomMediaStorageClient/standard_layout.html.twig' %}
<input type="file"
name="file"
class="file-upload"
data-url="{{ path('app.upload', {'client': 'sonata_media_client'}) }}">
Fetching Media Metadata
getMediaByReferenceFull service:
$media = $this->get('avtonom.media_storage_client.manager')
->getMediaByReferenceFull($referenceFullUrl);
Symfony Forms
use Avtonom\MediaStorageClientBundle\Form\Type\MediaType;
$builder->add('media', MediaType::class, [
'client' => 'sonata_media_client',
'context' => 'product_images',
]);
Validation
if (!$file->isValid()) {
throw new \RuntimeException('Invalid file upload.');
}
Context-Based Uploads
clients:
sonata_media_client:
base_url: "https://media-server.com"
contexts:
thumbnail: "/api/media/thumbnail"
original: "/api/media/original"
Error Handling
try {
$proxyMedia = $this->mediaStorageClient->sendFile($file, 'client_name');
} catch (\Exception $e) {
$this->addFlash('error', 'Upload failed: ' . $e->getMessage());
}
CORS Issues
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
File Size Limits
max_file_size (php.ini) and client_max_body_size (Nginx/Apache). Adjust these if uploads fail silently.Listener Overhead
prePersist/preUpdate. For large datasets, this can impact performance. Use selectively.Reference Full URL Mismatch
mediaReferenceFull doesn’t match the remote server’s expected format, uploads will fail. Verify the get_media_by_reference_full_url endpoint returns the correct structure.Deprecated BuzzBundle
sensio/buzz-bundle (v1.x), which is unmaintained. Monitor for HTTP client deprecation warnings.Enable Logging
logging_level to DEBUG (100) in config to trace HTTP requests:
logging_level: 100
[Buzz\Exception\CurlException] cURL error 6: Could not resolve host (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
Validate Endpoints
curl -X POST -F file=@test.jpg http://sonata-media-server/api/media/upload).ProxyMediaInterface Issues
media_get() returns ERROR: file not found, verify:
mediaReferenceFull URL is correct.getMediaByReferenceFull endpoint is accessible.Custom HTTP Client
services:
avtonom.media_storage_client.http_client:
class: Symfony\Contracts\HttpClient\HttpClientInterface
factory: ['Symfony\Component\HttpClient\HttpClient', 'create']
tags: ['avtonom.media_storage_client.http_client']
Pre/Post Upload Hooks
ObjectAddFileListener to add logic before/after uploads:
class CustomAddFileListener extends ObjectAddFileListener
{
public function run($entity, $eventName)
{
// Pre-upload logic
$result = parent::run($entity, $eventName);
// Post-upload logic
return $result;
}
}
Custom Media Metadata
ProxyMediaInterface to include additional fields (e.g., altText, copyright):
class CustomProxyMedia implements ProxyMediaInterface
{
private $altText;
public function setAltText(string $altText): void
{
$this->altText = $altText;
}
public function getAltText(): ?string
{
return $this->altText;
}
}
Multi-Part Uploads
sendFile method:
public function sendFileInChunks(UploadedFile $file, string $clientName, string $context = null)
{
$chunkSize = 5 * 1024 * 1024; // 5MB
$stream = $file->openFile();
$offset = 0;
while (!$stream->eof()) {
$chunk = $stream->read($chunkSize);
$this->sendChunk($chunk, $clientName, $context, $offset);
$offset += strlen($chunk);
}
}
Fallback for Offline Mode
try {
$proxyMedia = $this->mediaStorageClient->sendFile($file, 'sonata_media_client');
} catch (\Exception $e) {
$proxyMedia = $this->localStorage->store($file);
}
How can I help you explore Laravel packages today?