使用libmagic确定文件MIME类型【示例】

时间:2022-10-05 10:05:56

引用:   《http://blog.163.com/lixiangqiu_9202/blog/static/53575037201481310276358/》

没事写一个上传图片到imagebin.org的程序,但发现imagebin.org限制了上传的文件类型,这当然是可以理解的,imagebin.org为检查你上传的图片文件,如果与上传的文件MIME类型与Content-Type不一致的话会无法上传,我们当然可以手动根据自己上传的文件而设置Content-Type,但显然作为一个懒人,我更希望能够根据图片文件本身自动设置这个参数。

这个看起来根据文件的后缀名来确定Content-Type是一个不错的选择,毕竟是自己使用,但如果能有个库根据文件识别出MIME文件类型的话,那么我一定会很乐意的,没错,就是抱着这种心态我找到了libmagic,这是一个c语言库,Linux上file命令便是使用了这个库。

在linux下安装使用这个库非常简单,直接使用包管理器就可以安装了,我们安装后man libmagic可以查看到它的文档,libmagic可以做的不仅仅是检查文件的MIME类型,但这里我只说获取文件MIME类型,至于其它的,请自行查看libmagic文档。

想要查看文件MIME类型只需要知道4个函数就可以了,
magic_t magic_open(int flags);
int magic_load(magic_t cookie, const char *filename);
void magic_close(magic_t cookie);
const char *magic_file(magic_t cookie, const char *filename);

头文件

  1. #include <magic.h>

gcc编译时需要加上-lmagic参数

看函数名称就一目了然,先使用magic_open创建一个magic_t数据结构
再magic_load加载数据库
此时便可以使用magic_file进行检测了,使用完成后使用magic_close释放资源
可以说这是libmagic的使用方式。

想要获取文件MIME类型在调用magic_open时我们的flags要设置为MAGIC_MIME_TYPE,flags的具体参数可以参考libmagic文档
加载数据库时我们设置NULL来使用默认的数据库,默认的数据库linux一般是/usr/share/misc/magic.mgc,这取决于MAGIC这个系统变量。

下面是一个简单的示例

  1. #include <stdio.h>
  2. #include <magic.h>
  3.  
  4. int main(int argc,char **argv)
  5. {
  6.  magic_t cookie;
  7.  
  8.  cookie=magic_open(MAGIC_MIME_TYPE);
  9.  magic_load(cookie,NULL);
  10.  puts(magic_file(cookie,argv[1]));
  11.  magic_close(cookie);
  12.  
  13.  return 0;
  14. }

这切就是这么简单

下面干脆把上传图片到imagebin.org的程序也放上来吧,以免日后不小心丢掉了

  1. #include <stdio.h>
  2. #include <magic.h>
  3. #include <curl/curl.h>
  4.  
  5. size_t filtration_data(void *ptr,size_t size,size_t nmemb,void *data)
  6. {
  7.  return nmemb;
  8. }
  9.  
  10. int display_progress(void *clientp,double dltotal,double dlnow,
  11.   double ultotal,double ulnow)
  12. {
  13.  static int onece=0;
  14.  
  15.  if(ulnow/ultotal > 0)
  16.  {
  17.   if(ulnow >= ultotal)
  18.   {
  19.    if(onece) return 0;
  20.  
  21.    onece=1;
  22.   }
  23.  
  24.   printf("…%.0f%%",ulnow/ultotal*100);
  25.   fflush(stdout);
  26.  }
  27.  
  28.  return 0;
  29. }
  30.  
  31. int main(int argc,char **argv)
  32. {
  33.  CURL *curl;
  34.  char *url="http://imagebin.org/index.php";
  35.  struct curl_httppost *post=NULL,*last=NULL;
  36.  char *res;
  37.  const char *content_type;
  38.  magic_t cookie;
  39.  
  40.  cookie=magic_open(MAGIC_MIME_TYPE);
  41.  if(!cookie)
  42.  {
  43.   perror("magic_open");
  44.   return -1;
  45.  }
  46.  
  47.  if(magic_load(cookie,NULL) == -1)
  48.  {
  49.   printf("%s\n",magic_error(cookie));
  50.   magic_close(cookie);
  51.   return -1;
  52.  }
  53.  
  54.  content_type=magic_file(cookie,argv[1]);
  55.  if(!content_type)
  56.  {
  57.   puts(magic_error(cookie));
  58.   magic_close(cookie);
  59.   return -1;
  60.  }
  61.  
  62.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"nickname",
  63.    CURLFORM_COPYCONTENTS,"test",CURLFORM_END);
  64.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"remember_nickname",
  65.    CURLFORM_COPYCONTENTS,"N",CURLFORM_END);
  66.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"image",
  67.    CURLFORM_FILE,argv[1],
  68.    CURLFORM_CONTENTTYPE,content_type,CURLFORM_END);
  69.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"title",
  70.    CURLFORM_COPYCONTENTS,"test",CURLFORM_END);
  71.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"description",
  72.    CURLFORM_COPYCONTENTS,"test",CURLFORM_END);
  73.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"disclaimer_agree",
  74.    CURLFORM_COPYCONTENTS,"Y",CURLFORM_END);
  75.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"Submit",
  76.    CURLFORM_COPYCONTENTS,"Submit",CURLFORM_END);
  77.  curl_formadd(&post,&last,CURLFORM_COPYNAME,"mode",
  78.    CURLFORM_COPYCONTENTS,"add",CURLFORM_END);
  79.  
  80.  curl=curl_easy_init();
  81.  curl_easy_setopt(curl,CURLOPT_URL,url);
  82.  curl_easy_setopt(curl,CURLOPT_HTTPPOST,post);
  83.  curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
  84.  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,filtration_data);
  85.  curl_easy_setopt(curl,CURLOPT_USERAGENT,"Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0");
  86.  curl_easy_setopt(curl,CURLOPT_NOPROGRESS,0);
  87.  curl_easy_setopt(curl,CURLOPT_PROGRESSFUNCTION,display_progress);
  88.  
  89.  curl_easy_perform(curl);
  90.  curl_easy_getinfo(curl,CURLINFO_EFFECTIVE_URL,&res);
  91.  printf("\n%s\n",res);
  92.  curl_easy_cleanup(curl);
  93.  curl_formfree(post);
  94.  magic_close(cookie);
  95.  
  96.  return 0;
  97. }
依葫芦 画瓢 : 
#include <stdio.h>
#include <magic.h>

int main(int argc,char **argv)
{
 struct magic_set   *cookie = NULL;

 cookie=magic_open(MAGIC_MIME);
 magic_load(cookie, NULL);
 puts(magic_file(cookie,argv[1]));
 magic_close(cookie);

 return 0;
}