当文件的type属性为"audio/mpeg"时,为什么Laravel的getMimeType()方法将文件识别为"application/octet-stream"?

Kir*_*and 16 php laravel flysystem

我正在尝试将一个MP3文件上传到Laravel应用程序并遇到一个问题,即使该文件的属性设置为"audio/mpeg",它也会上传为"application/octet-stream"(.bin)文件.当我尝试死亡并将文件转储到服务器端代码时:

dd($request->file('file'));
Run Code Online (Sandbox Code Playgroud)

我明白了:

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
}
Run Code Online (Sandbox Code Playgroud)

看看我何时使用这种方法,确实说mimeType的文件属性是正确的"audio/mpeg"格式.但是当我上传文件后调用getMimeType()方法时,我得到:

"application/octet-stream"
Run Code Online (Sandbox Code Playgroud)

这是路由方法中的代码:

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

这个问题看起来很独特,因为我使用的是Laravel框架,其他有这个问题的人使用的是vanilla PHP.此外,其他人可能使用的excel文件可能已将自身报告为应用程序/八位字节流而不是excel文件.最后,我相信这可能是guess()方法的一个问题,它由getMethodType()调用.拥有更多Laravel经验的人可能会证实这一点.

Leo*_*mer 20

UploadedFile对象最终扩展,Symfony\Component\HttpFoundation\File\UploadedFile从中获取/设置mimeType The type of the file as provided by PHP.

要访问您需要调用的mimeType $file->getClientMimeType()

但是在Symfony docblock中它建议的功能:

客户端mime类型是从上载文件的请求中提取的,因此不应将其视为安全值.

对于受信任的mime类型,请改用getMimeType()(根据文件内容猜出mime类型).

在你的情况下$file->getMimeType(),应该是可信任的并从内容中猜测mime类型,但它返回的东西好像它无法确定mime类型,是"application/octet-stream"

附加信息

帮你决定.基本上getClientMimeType()会返回浏览器设置的mime类型.

getMimeType调用使用我可以看到的两种不同技术猜测mime类型:

  1. file -b --mime %s 2>/dev/null如果支持,则使用二进制mime类型技术查看以下命令的输出.

  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');
Run Code Online (Sandbox Code Playgroud)

回报 application/x-iso9660-image


jam*_*yle 6

我在Laravel 5.4中遇到过这个问题.我通过设置post_max_sizeupload_max_filesizephp.ini的更高值来修复.

之后,我实际上不得不重新启动OSX才能真正反映出应用程序.