之前公司的项目需要自定义一种文件类型,但是由于存储的是普通文本文件,文件上传后用php的finfo判断文件类型的时候还是会被识别为txt类型,今天看到了,在linux下可以通过修改/etc/magic 文件来实现自定义文件类型,通过man magic可以查看到详细的自定义文件格式的帮助信息。问题来了,windows下怎么实现呢,貌似finfo扩展使用的是自己的magic库,也就是说我们如果能够修改的话,即使是windows下这种方式依然是可行的。
finfo_open()
<?php
$fo = finfo_open('FILEINFO_MIME_TYPE')
$type = finfo_file($fo, 'test');
通过上面简单的代码,我们就可以获取到文件的mime信息,但是只能获取到finfo扩展定义的, 如果我们想自己定义呢?仔细阅读finfo_open() 我们可以看到,第二个参数是让指定magic_file, 这又是什么呢?
magic_file
包含了多种文件特征签名的文件。
通过阅读维基百科文档关于文件格式的内容 我们可以发现,文件格式的识别,一共有3种方式
-
通过文件的扩展名,
.exe , .txt , .rmvb, windows 操作系统采用的方式。 -
特征签名, unix 类及其派生类操作系统
特征签名是通过在文件的特定位置,一般是前几个字节,放置一些描述该文件的信息,来进行识别。例如Gif 图片通过前六个字节来进行识别
GIF87a,GIF89a -
元数据
将文件格式信息存放到磁盘特定的位置。
采用这种方式,元数据与文件本身份开存放。此法的缺点是可移植性差。因为不同的文件系统之间元数据可能需要转换。
自定义文件类型
通过上面的介绍,我们应该知道计算机是怎么识别不同类型的文件了,现在我们就是要自己创建一个属于自己的文件类型。通过查看php的源码我们应该能够看到,php内置的magic库使用的是来自Fossies 软件源中 file 这个软件,下载解压之后,我们能够在magic/Magdir/ 下面发现很多文件,这些文件中就定义了很多种文件的特征签名。 我们可以根据man magic 中介绍的规则定义自己的类型。
0 search/1/c =akg akg file
!:mime text/akg
//最简单的一种定义方式,适合普通文件文件
-
普通文本类
如果我们自定义的文件类型是,普通文本文件,类似脚本文件这种,自然是很好定义的,只需要在文件头部,写一些特定的字符就行了。
-
二进制类
如果我们定义的文件并不想被普通文本编辑器打开,那么我们可以使用php的一对函数来写入,他们的功能是负责将数据转换成二进制,并解码二进制文件,他们是 pack 和 unpack
可以参考这篇文章 pack()&unpack() &ord()
自定义magic_file的使用方式
我们有两种方式使用,自定义的magic文件。
- 环境变量,Linux 下我们可以通过简单的使用
export MAGIC='/path/to/magic_file'来定义环境变量,但是重启之后会失效,也可以通过在/etc/profile中永久定义。windows 下就不用说了吧。 - 指定文件路径,这种方式的话,我们只能指定一个文件了,所以我们有必要把所有的特征签名整合到一个文件中去,然后
finfo_open('FILEINFO_MIME_TYPE', '/path/to/magic_file')