Почему метод getMimeType() Laravel идентифицирует файл как "application/octet-stream", если файл имеет атрибут type "audio/mpeg"?

Я пытаюсь загрузить файл MP3 в приложение Laravel и столкнулся с проблемой, когда файл имеет атрибут "audio/mpeg", но он загружен как "application/octet-stream" (.bin). файл. Когда я пытаюсь умереть и сбросить файл на серверный код с помощью:

dd($request->file('file'));

Я получил:

UploadedFile {#187 ▼
  -test: false
  -originalName: "CUS12309821-20-AUG-2016-13-48-13.mp3"
  -mimeType: "audio/mpeg"
  -size: 47000471
  -error: 0
  path: "/private/var/folders/c7/6ws0lxy95dd_lhz1k067_zkc0000gn/T"
  filename: "phpyZCsbU"
  basename: "phpyZCsbU"
  pathname: "/private/var/folders/c7/6ws0lxy95dd_lhz1k067_zkc0000gn/T/phpyZCsbU"
  extension: ""
  realPath: "/private/var/folders/c7/6ws0lxy95dd_lhz1k067_zkc0000gn/T/phpyZCsbU"
  aTime: 2016-09-20 12:56:00
  mTime: 2016-09-20 12:56:00
  cTime: 2016-09-20 12:56:00
  inode: 4565593
  size: 47000471
  perms: 0100600
  owner: 501
  group: 20
  type: "file"
  writable: true
  readable: true
  executable: false
  file: true
  dir: false
  link: false
}

Посмотрите, как, когда я использую этот метод, он действительно говорит, что атрибут файла для mimeType является правильным форматом "audio/mpeg". Однако когда я вызываю метод getMimeType() для файла после его загрузки, я получаю:

"application/octet-stream"

Вот код в маршрутизируемом методе:

/**
 * Store a newly created resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $file = $request->all();

    $filePath = Storage::putFile('file', $request->file('files'));

    dd($request->file('file')->getMimeType());

    $file['path'] = Storage::url($filePath);
    $file['size'] = Storage::size($filePath);
    $file['type'] = $request->file('file')->getMimeType();

    return $file;
}

Эта проблема на первый взгляд уникальна тем, что я использую фреймворк Laravel, где другие с этой проблемой используют ванильный PHP. Кроме того, файл Excel, который могут быть использованы другими, возможно, сообщил о себе как о приложении / октет-потоке вместо файла Excel. Наконец, я полагаю, что это может быть проблемой с методом предположения (), который вызывается методом getMethodType(). Кто-то с большим опытом Laravel мог бы это подтвердить.

3 ответа

Решение

UploadedFile объект в конечном итоге расширяется от Symfony\Component\HttpFoundation\File\UploadedFile который получает / устанавливает mimeType из The type of the file as provided by PHP,

Для доступа к этому mimeType вам нужно будет позвонить $file->getClientMimeType()

Однако в докблоке Symfony для этой функции предлагается:

Тип MIME клиента извлекается из запроса, из которого был загружен файл, поэтому его не следует рассматривать как безопасное значение.

Для доверенного типа MIME используйте взамен getMimeType() (который угадывает тип MIME на основе содержимого файла).

В вашем случае однако $file->getMimeType() который должен быть доверенным и угадывает тип MIME из содержимого, однако он возвращает что-то, как будто он не может определить тип MIME, будучи "application / octet-stream"

Дополнительная информация

Чтобы помочь вам решить. В принципе getClientMimeType() вернет тип MIME, который был установлен браузером.

getMimeType Call угадывает MIME-тип, используя два разных метода, которые я вижу:

  1. Используя бинарную технику mime-типов, просматривая вывод следующей команды file -b --mime %s 2>/dev/null если это поддерживается.

  2. Второй метод использует finfo_open команда, если она существует внутри php.

Если в вашей системе есть и 1. и 2., из того, что я вижу 2. предпочтет, а 1. будет запасным вариантом.

Я лично предпочел бы результаты от getMimeType() для обеспечения безопасности. Тем не менее, было бы еще один интересный вопрос: "Насколько надежно обнаружение типа mime в браузере и какие методы используются":-)

Обновленный пример

Я приведу пример для вас.

Для меня, делающего проверку на DropboxInstalled.dmg, вот мои результаты:

  1. с помощью file -b --mime DropboxInstaller.dmg из командной строки (терминала) возвращает application/octet-stream

  2. с помощью finfo_open функциональность

$finfo = new \finfo(FILEINFO_MIME_TYPE);
echo $finfo->file('./DropboxInstaller.dmg');

возвращается application/x-iso9660-image

У меня была эта проблема с Laravel 5.4. Я исправил установкой post_max_size а также upload_max_filesize в моем php.ini на более высокое значение.

После этого мне пришлось сделать жесткий перезапуск OSX, прежде чем он действительно отобразится в приложении должным образом.

Я получил эту ошибку сapplication/octet-streamв моем приложении Laravel 9, когда загружаемые мной файлы были слишком большими.

Для меня это решило установка этих двух настроек (увеличение пределов) в.iniфайл:

      post_max_size = 128M
upload_max_filesize = 128M
Другие вопросы по тегам