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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39594854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:58:10  来源:igfitidea点击:

Why does Laravel's getMimeType() method identify a file as "application/octet-stream" when the file has the type attribute of "audio/mpeg"?

phplaravelflysystem

提问by Kirkland

I'm trying to upload a MP3 file to a Laravel application and have ran into an issue where even though the file has an attribute set to "audio/mpeg" it is uploaded as a "application/octet-stream" (.bin) file. When I try to die and dump the file on the server-side code with:

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

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

I get:

我得到:

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
}

Look at how when I use this method, it does indeed say that the file attribute for mimeType is the correct "audio/mpeg" format. However when I call the getMimeType() method on the file after it's uploaded, I get:

看看当我使用这个方法时,它确实说 mimeType 的文件属性是正确的“音频/mpeg”格式。但是,当我在文件上传后调用 getMimeType() 方法时,我得到:

"application/octet-stream"

Here's the code in the routed method:

这是路由方法中的代码:

/**
 * 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;
}

This problem is seemingly unique in that I'm using the Laravel framework, where others with this problem are using vanilla PHP. Additionally, the excel file others may us may have reported itself as a application/octet-stream instead of an excel file. Finally, I believe this may be a issue with the guess() method, which is called by the getMethodType(). Someone with more Laravel experience could probably confirm this.

这个问题似乎是独一无二的,因为我使用的是 Laravel 框架,而其他有此问题的人正在使用普通 PHP。此外,我们其他人可能将 excel 文件报告为应用程序/八位字节流而不是 excel 文件。最后,我认为这可能是由 getMethodType() 调用的 guess() 方法的问题。有更多 Laravel 经验的人可能会证实这一点。

回答by Leon Vismer

The UploadedFileobject is ultimately extended from Symfony\Component\HttpFoundation\File\UploadedFilewhich get/sets the mimeType from The type of the file as provided by PHP.

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

To access that mimeType you would need to call $file->getClientMimeType()

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

However in the Symfony docblock for the function it suggests:

然而,在 Symfony docblock 中它建议的函数:

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).

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

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

In your case however $file->getMimeType()which should be trusted and guesses the mime type from the contents, however it returns something as if it cannot determine the mime type, being "application/octet-stream"

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

Additional information

附加信息

To help you decide. Basically getClientMimeType()would return the mime type that was set by the browser.

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

The getMimeTypecall guesses the mime type using two different techniques that I can see:

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

  1. Using a binary mime type technique looking at the output of the following command file -b --mime %s 2>/dev/nullif it is supported.

  2. The second technique is using the finfo_opencommand if it does exist inside php.

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

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

If both 1. and 2. exists on your system, from what I see 2. will take preference, and 1. will be the fallback.

如果 1. 和 2. 都存在于您的系统上,从我看来 2. 将优先,而 1. 将作为后备。

I personally would favour the results from getMimeType()for security. However, it would be another interesting question to ask "How reliable is browser mime type detection, and what techniques are used" :-)

我个人更喜欢getMimeType()安全性的结果。但是,另一个有趣的问题是“浏览器 mime 类型检测的可靠性,以及使用了哪些技术”:-)

Updated example

更新示例

I include an example for you.

我给你举了一个例子。

For me doing a check on a "DropboxInstalled.dmg", here are my results:

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

  1. using file -b --mime DropboxInstaller.dmgfrom a commandline (terminal) returns application/octet-stream

  2. using finfo_openfunctionality

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

  2. 使用finfo_open功能

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

returns application/x-iso9660-image

返回 application/x-iso9660-image

回答by james2doyle

I was having this issue with Laravel 5.4. I fixed by setting post_max_sizeand upload_max_filesizein my php.inito a higher value.

我在 Laravel 5.4 上遇到了这个问题。我通过设置post_max_sizeand upload_max_filesizein myphp.ini来修复更高的值。

After that, I actually had to do a hard restart of OSX before it would actually reflect in the application properly.

在那之后,我实际上不得不硬重启 OSX,然后它才能真正正确地反映在应用程序中。