为什么 Laravel 的 getMimeType() 方法将文件标识为“application/octet-stream”,而该文件的类型属性为 “audio/mpeg”?

2022-08-30 13:07:12

我正在尝试将MP3文件上传到Laravel应用程序,并遇到了一个问题,即使该文件的属性设置为“audio / mpeg”,它也被上传为“应用程序/八位字节流”(.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 文件报告为应用程序/八位字节流,而不是 Excel 文件。最后,我相信这可能是 guess() 方法的问题,它由 getMethodType() 调用。具有更多Laravel经验的人可能会证实这一点。


答案 1

该对象最终被扩展,从中获取/设置来自 的 mimeType。UploadedFileSymfony\Component\HttpFoundation\File\UploadedFileThe type of the file as provided by PHP

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

然而,在Symfony文档块中,它建议的功能是:

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

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

然而,在你的情况下,它应该是可信的,并从内容中猜测哑剧类型,但是它返回的东西好像它无法确定哑剧类型,是“应用程序/八位字节流”$file->getMimeType()

附加信息

帮助您做出决定。基本上会返回浏览器设置的哑剧类型。getClientMimeType()

呼叫使用我可以看到的两种不同技术猜测哑剧类型:getMimeType

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

  2. 第二种技术是使用该命令,如果它确实存在于php中。finfo_open

如果两者都是 1.和 2.存在于您的系统上,从我所看到的2。将优先,和 1.将是后备方案。

我个人赞成从安全角度得出的结果。但是,询问“浏览器哑剧类型检测的可靠性如何,以及使用什么技术”将是另一个有趣的问题:-)getMimeType()

更新的示例

我为你举个例子。

对于我检查“DropboxInstalled.dmg”,这是我的结果:

  1. 使用从命令行(终端)返回file -b --mime DropboxInstaller.dmgapplication/octet-stream

  2. 使用功能finfo_open

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

返回application/x-iso9660-image


答案 2

我在Laravel 5.4上遇到了这个问题。我通过设置和在我的到更高的值来固定。post_max_sizeupload_max_filesizephp.ini

在那之后,我实际上必须对OSX进行硬重启,然后才能在应用程序中正确反映。


推荐