cURL / Mailing Lists / curl-and-php / Single Mail

curl-and-php

Set content-type for http post upload file not possible

From: Morgan Galpin <morgan_at_atsourceinc.ca>
Date: Wed, 12 Dec 2007 14:19:06 -0800

The question has been asked a few times previously, "How can I set the
Content-Type for files in a multipart/form-data post?", but there hasn't
been a definitive answer that I can find. I had the same question, but
now I have the answer.

The goal is to produce something like the following:
[...]
Content-Type: multipart/form-data;
boundary=----------------------------19566f682317
------------------------------19566f682317
Content -Disposition: form-data; name="uploadFile"; filename="filename.pdf"
Content-Type: application/pdf
[...]

The answer to the question, I'm sad to report, is it's not possible.

Curl always seems to send "Content-Type: application/octet-stream",
which for some servers doesn't work. My browser of choice, Firefox, will
send " Content-Type: application/pdf" for the pdf that I'm trying to
upload. The server I'm trying to send data to won't accept the
application/octet-stream type.

It can be accomplished with the curl command line, by adding the
following to the command:
    -F "uploadFile=@filename.pdf;type=application/pdf"

The part after the semi-colon specifies the content type for that file.
See http://curl.haxx.se/docs/manual.html in the "POST (HTTP)" section.

However if I try the same syntax with PHP/cURL, I get the error, "failed
creating formpost data" using the following:
<?php

  // Set parameters.
  $url = "http://www.example.com/";
 
  // Set up the post data.
  $postData = array(
    'uploadFile' => '@filename.pdf;type=application/pdf',
  );
 
  // Create the curl handle with the data to send.
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  curl_setopt($ch, CURLOPT_URL, $url);
 
  // Get the result.
  $result = curl_exec($ch);

  // Close the handle.
  curl_close($ch);
 
?>

This happens because the cURL interface for PHP specifically checks for
the existence of the filename after the '@' character. Since it is not
only a file name, it fails. It should be able to parse out the "type="
directives instead of only using a filename.

Another option would be for cURL to automatically figure out the mime
type of the file based on the contents or file extension. It can, but
only for 5 file extensions:
    {".gif", "image/gif"},
    {".jpg", "image/jpeg"},
    {".jpeg", "image/jpeg"},
    {".txt", "text/plain"},
    {".html", "text/html"}

If the end of the filename matches one of the extensions, then it will
insert the associated mime type for the "Content-type:". If it isn't one
of the 5, then the mime type is "application/octet-stream". These 6
types are hard-coded into cURL. There is no way to change the set of
mime types without modifying the source code and recompiling it. :-( It
should read some kind of mime.magic file instead.

If either the PHP-curl interface or cURL code were changed to
accommodate this kind of upload, I could get my application to work.
They should both be changed and I hope one day they will be. Until that
time, I'm going to have to come up with some other way of posting to
this server.

I hope this information is able to help someone save themselves a few
hours of hair-pulling.
Morgan Galpin.
_______________________________________________
http://cool.haxx.se/cgi-bin/mailman/listinfo/curl-and-php
Received on 2007-12-12