为什么 Laravel 的 getMimeType() 方法在文件具有 "audio/mpeg" 的类型属性时将文件识别为 "application/octet-stream"?
Why does Laravel's getMimeType() method identify a file as "application/octet-stream" when the file has the type attribute of "audio/mpeg"?
我正在尝试将 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
,get/sets mimeType 来自 The type of the file as provided by PHP
。
要访问该 mimeType,您需要调用 $file->getClientMimeType()
但是在 Symfony 文档块中它建议的函数:
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 类型,但是它 return 好像它无法确定 mime 类型,是“application/octet-stream"
附加信息
帮你决定。基本上 getClientMimeType()
会 return 浏览器设置的 mime 类型。
getMimeType
调用使用我可以看到的两种不同技术来猜测 MIME 类型:
使用二进制 MIME 类型技术查看以下命令的输出 file -b --mime %s 2>/dev/null
(如果支持)。
第二种方法是使用 finfo_open
命令,如果它确实存在于 php.
如果 1. 和 2. 都存在于您的系统中,据我所知,2. 将优先,1. 将是后备。
出于安全考虑,我个人更喜欢 getMimeType()
的结果。但是,问“浏览器 mime 类型检测的可靠性如何,以及使用了哪些技术”将是另一个有趣的问题:-)
更新示例
我为您提供了一个示例。
我检查了“DropboxInstalled.dmg”,结果如下:
从命令行(终端)使用 file -b --mime DropboxInstaller.dmg
returns application/octet-stream
使用 finfo_open
功能
$finfo = new \finfo(FILEINFO_MIME_TYPE);
echo $finfo->file('./DropboxInstaller.dmg');
returns application/x-iso9660-image
我在使用 Laravel 5.4 时遇到了这个问题。我通过将 php.ini
中的 post_max_size
和 upload_max_filesize
设置为更高的值来修复。
在那之后,我实际上不得不硬重启 OSX 才能真正正确地反映在应用程序中。
我正在尝试将 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
,get/sets mimeType 来自 The type of the file as provided by PHP
。
要访问该 mimeType,您需要调用 $file->getClientMimeType()
但是在 Symfony 文档块中它建议的函数:
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 类型,但是它 return 好像它无法确定 mime 类型,是“application/octet-stream"
附加信息
帮你决定。基本上 getClientMimeType()
会 return 浏览器设置的 mime 类型。
getMimeType
调用使用我可以看到的两种不同技术来猜测 MIME 类型:
使用二进制 MIME 类型技术查看以下命令的输出
file -b --mime %s 2>/dev/null
(如果支持)。第二种方法是使用
finfo_open
命令,如果它确实存在于 php.
如果 1. 和 2. 都存在于您的系统中,据我所知,2. 将优先,1. 将是后备。
出于安全考虑,我个人更喜欢 getMimeType()
的结果。但是,问“浏览器 mime 类型检测的可靠性如何,以及使用了哪些技术”将是另一个有趣的问题:-)
更新示例
我为您提供了一个示例。
我检查了“DropboxInstalled.dmg”,结果如下:
从命令行(终端)使用
file -b --mime DropboxInstaller.dmg
returnsapplication/octet-stream
使用
finfo_open
功能
$finfo = new \finfo(FILEINFO_MIME_TYPE);
echo $finfo->file('./DropboxInstaller.dmg');
returns application/x-iso9660-image
我在使用 Laravel 5.4 时遇到了这个问题。我通过将 php.ini
中的 post_max_size
和 upload_max_filesize
设置为更高的值来修复。
在那之后,我实际上不得不硬重启 OSX 才能真正正确地反映在应用程序中。