web-dev-qa-db-ja.com

LaravelのgetMimeType()メソッドは、ファイルのタイプ属性が「audio / mpeg」であるときに、「application / octet-stream」としてファイルを識別するのはなぜですか?

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フレームワークを使用している点で一見ユニークです。この問題を抱える他の人はVanilla PHPを使用しています。さらに、Excelファイルは、最後に、これは、getMethodType()によって呼び出されるguess()メソッドの問題である可能性があると思います。Laravelの経験がある人はおそらくこれを確認してください。

15
Kirkland

UploadedFileオブジェクトは、最終的に_Symfony\Component\HttpFoundation\File\UploadedFile_から拡張され、_The type of the file as provided by PHP_からmimeTypeを取得/設定します。

そのmimeTypeにアクセスするには、$file->getClientMimeType()を呼び出す必要があります

ただし、関数のSymfonyのdocblockでは、次のことを示唆しています:

クライアントMIMEタイプは、ファイルのアップロード元のリクエストから抽出されるため、安全な値と見なされるべきではありません。

信頼できるMIMEタイプの場合は、代わりにgetMimeType()を使用します(ファイルの内容に基づいてMIMEタイプを推測します)。

しかし、あなたの場合は$file->getMimeType()は信頼され、コンテンツからMIMEタイプを推測する必要がありますが、MIMEタイプを決定できないかのように「application/octet-stream」で何かを返します。

追加情報

あなたが決めるのを助けるために。基本的に、getClientMimeType()は、ブラウザによって設定されたMIMEタイプを返します。

getMimeType呼び出しは、私が見ることができる2つの異なる手法を使用してMIMEタイプを推測します。

  1. サポートされている場合は、次のコマンド_file -b --mime %s 2>/dev/null_の出力を調べるバイナリMIMEタイプの手法を使用します。

  2. 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_を返します

16
Leon Vismer

Laravel 5.4でこの問題が発生していました。post_max_sizeおよびupload_max_filesize私のphp.iniをより高い値に。

その後、実際にアプリケーションに適切に反映される前に、OSXをハードリスタートする必要がありました。

6
james2doyle