首先:我完全知道这个问题的创建日期,但我最近偶然发现了同样的问题,我想上传一个 mp3 文件并将文件扩展名保留为 mp3 而不是将其切换为 mpga。而且据我所知,在过去的三年里,没有简单的解决方案添加到源代码中......
我很确定我的解决方案不是最好的,但它只需添加少量代码即可完成工作:)
BinaryContent
在我的项目中,我必须通过将对象的 设置为Media
Symfony类来上传文件Request
,这导致问题恰好出现在这一行:
// FileProvider.php#L483
$guesser = ExtensionGuesser::getInstance();
$extension = $guesser->guess($media->getContentType());
该类从 SymfonyFileProvider
获取实例,ExtensionGuesser
并让他猜测给定 ContentType 的扩展名应该是什么:
// MimeTypeExtensionGuesser.php#L623
'audio/mpeg' => 'mpga',
在我看来,如果我们可以添加自己的MimeType->Extension
映射或简单地替换 ExtensionGuesser 的类并在配置文件中进行一些小的更改,那就太好了。但是没有人知道像我们这样的三个人不想上传一个mp3文件并将扩展名切换为mpga......所以没有这样的解决方案。
但我们实际上可以更改 classNameFileProvider
并覆盖我们想要做不同事情的方法:
// app/config/services.yml
parameters:
sonata.media.provider.file.class: Application\Sonata\MediaBundle\Provider\FileProvider
// Application\Sonata\MediaBundle\Provider\FileProvider:
<?php
namespace Application\Sonata\MediaBundle\Provider;
use Sonata\MediaBundle\Extra\ApiMediaFile;
use Sonata\MediaBundle\Model\MediaInterface;
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
use Symfony\Component\HttpFoundation\Request;
/**
* Class FileProvider
*
* @package Application\Sonata\MediaBundle\Provider
*/
class FileProvider extends \Sonata\MediaBundle\Provider\FileProvider
{
/**
* @var array
*/
protected $contentTypeMapping = [
'audio/mpeg' => 'mp3'
];
/**
* Set media binary content according to request content.
*
* @param MediaInterface $media
*/
protected function generateBinaryFromRequest(MediaInterface $media)
{
if (php_sapi_name() === 'cli') {
throw new \RuntimeException('The current process cannot be executed in cli environment');
}
if (!$media->getContentType()) {
throw new \RuntimeException(
'You must provide the content type value for your media before setting the binary content'
);
}
$request = $media->getBinaryContent();
if (!$request instanceof Request) {
throw new \RuntimeException('Expected Request in binary content');
}
$content = $request->getContent();
$extension = $this->getExtension($media->getContentType());
$handle = tmpfile();
fwrite($handle, $content);
$file = new ApiMediaFile($handle);
$file->setExtension($extension);
$file->setMimetype($media->getContentType());
$media->setBinaryContent($file);
}
/**
* Returns the fileExtension for a given contentType
*
* First of all, we have to look at our own mapping and if we have no mapping defined, just use the ExtensionGuesser
*
* @param string $contentType
*
* @return string
*/
private function getExtension($contentType)
{
if (array_key_exists($contentType, $this->contentTypeMapping)) {
return $this->contentTypeMapping[$contentType];
}
// create unique id for media reference
$guesser = ExtensionGuesser::getInstance();
$extension = $guesser->guess($contentType);
if (!$extension) {
throw new \RuntimeException(
sprintf('Unable to guess extension for content type %s', $contentType)
);
}
return $extension;
}
}
到目前为止,它运行得很好,我对此没有任何问题:)