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

标签 php laravel flysystem

我正在尝试将 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 文件报告为 application/octet-stream 而不是 excel 文件。最后,我认为这可能是 getMethodType() 调用的 guess() 方法的问题。具有更多 Laravel 经验的人可能会证实这一点。

最佳答案

UploadedFile 对象最终扩展自 Symfony\Component\HttpFoundation\File\UploadedFile,它从 获取/设置 mimeType 提供的文件类型通过 PHP

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

但是在 Symfony 文档 block 中它建议的功能:

The client mime type is extracted from the request from which the file was uploaded, so it should not be considered as a safe value.

For a trusted mime type, use getMimeType() instead (which guesses the mime type based on the file content).

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

附加信息

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

getMimeType 调用使用我看到的两种不同技术来猜测 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

关于php - 当文件的类型属性为 "application/octet-stream"时,为什么 Laravel 的 getMimeType() 方法将文件识别为 "audio/mpeg"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39594854/

相关文章:

php - laravel 中如何获取列表的第一个元素?

php - Laravel 迁移名称太长

php - SQLSTATE[HY000] : General error: 1005 Can't create table `Projectname` .`users` (errno: 150 "Foreign key constraint is incorrectly formed")

php - 不破解 CurlException : 60 (cURL SSL Certificate Verification)

php - 如果值为真,则应选中复选框

laravel - Anvard HybridAuth Laravel 实现 - 无法重定向到空 URL

php - 在 PHP 中使用 Flysystem 从 S3 下载文件

laravel - 使用 Laravel 从 Web 服务器流式传输 Amazon S3 对象

php - Laravel - 将 PHP 资源传递给 Storage::put

php - 如何根据可用时段和预订时段找到空闲时段?