3

When uploading a file as a form field in curl (for example, curl -F 'file=@path/to/file' https://example.org/upload), curl sometimes sets the MIME type differently than what is returned by other utilities determining MIME type.

For example, on .bmp bitmap files, file -i path/to/file.bmp says it's image/x-ms-bmp, but curl sets the MIME type to application/octet-stream unless I explicitly override it.

However, it works properly for some file types, such as .png and .jpg.

I would like to know how it determines the MIME type and under what conditions it will work as expected.

3

From some source code spelunking for Content-Type curl appears to do some file extension matching otherwise defaulting to HTTPPOST_CONTENTTYPE_DEFAULT which is application/octet-stream, in the oddly named ContentTypeForFilename function:

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

(Though I suppose the source could be modified to do file(1) type magic checks in the future, maybe...)

  • Thanks! Seems like this would be a fairly easy thing to patch for more file support at one point, and something better than simply using the file extension. – markasoftware Oct 5 '17 at 23:53
  • Yeah you could save PNG data or whatever as a foo.jpg and then who knows how bad it gets depending on what the server and any other software does with that... – thrig Oct 6 '17 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.