命令行中的“curl”如何确定正在上传的文件的MIME类型?

命令行中的“curl”如何确定正在上传的文件的MIME类型?

当将文件作为表单字段上传curl(例如curl -F 'file=@path/to/file' https://example.org/upload)时,curl有时会设置MIME类型与确定 MIME 类型的其他实用程序返回的内容不同。

例如,在位.bmp图文件上,file -i path/to/file.bmp表示它是image/x-ms-bmp,但curl将 MIME 类型设置为 ,application/octet-stream除非我明确覆盖它。

但是,它适用于某些文件类型,例如.png.jpg

我想知道它如何确定 MIME 类型以及在什么条件下它会按预期工作。

答案1

从一些源代码中,spelunking forContent-Type curl似乎会进行一些文件扩展名匹配,否则默认为HTTPPOST_CONTENTTYPE_DEFAULTwhich is application/octet-stream,在奇怪的命名ContentTypeForFilename函数中:

https://github.com/curl/curl/blob/ee56fdb6910f6bf215eecede9e2e9bfc83cb5f29/lib/formdata.c#L166

static const char *ContentTypeForFilename(const char *filename,
                                          const char *prevtype)
{
  const char *contenttype = NULL;
  unsigned int i;
  /*
   * No type was specified, we scan through a few well-known
   * extensions and pick the first we match!
   */
  struct ContentType {
    const char *extension;
    const char *type;
  };
  static const struct ContentType ctts[]={
    {".gif",  "image/gif"},
    {".jpg",  "image/jpeg"},
    {".jpeg", "image/jpeg"},
    {".txt",  "text/plain"},
    {".html", "text/html"},
    {".xml", "application/xml"}
  };

  if(prevtype)
    /* default to the previously set/used! */
    contenttype = prevtype;
  else
    contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;

  if(filename) { /* in case a NULL was passed in */
    for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
      if(strlen(filename) >= strlen(ctts[i].extension)) {
        if(strcasecompare(filename +
                          strlen(filename) - strlen(ctts[i].extension),
                          ctts[i].extension)) {
          contenttype = ctts[i].type;
          break;
        }
      }
    }
  }
  /* we have a contenttype by now */
  return contenttype;
}

file(1)(虽然我认为将来可以修改源代码以进行类型魔术检查,也许......)

相关内容