1

I'm trying to construct a PHP POST request that includes some binary data, following on from a previous StackOverflow question. The data is being submitted to this API call: http://www.cyclestreets.net/api/#addphoto

This is my PHP code:

$file = $_FILES['mediaupload'];
$file_field="@$file[tmp_name]";
$fields = array(
    'mediaupload'=>$file_field,
    'username'=>urlencode($_POST["username"]),
    'password'=>urlencode($_POST["password"]),
    'latitude'=>urlencode($_POST["latitude"]),
    'longitude'=>urlencode($_POST["longitude"]),
    'datetime'=>urlencode($_POST["datetime"]),
    'category'=>urlencode($_POST["category"]),
    'metacategory'=>urlencode($_POST["metacategory"]),
    'caption'=>urlencode($_POST["description"])
);
$fields_string = http_build_query($fields);
echo 'FIELDS STRING: ' . $fields_string;
$url = 'https://www.cyclestreets.net/api/addphoto.json?key=$key';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec ($ch);

This is what my PHP file outputs:

FIELDS STRING: mediaupload=%40%2Fprivate%2Fvar%2Ftmp%2FphpHjfkRP&username=testing&password=testing&latitude=auto&longitude=auto&datetime=auto&category=cycleparking&metacategory=good&caption=
API RESPONSE: {"request":{"datetime":"1309886656"},"error":{"code":"unknown","message":"The photo was received successfully, but an error occurred while processing it."},"result":{}}

I believe this means that everything else about the request is OK, apart from the format of the binary data. Can anyone tell me what I am doing wrong?

1
  • You want to send the file from $_FILES['mediaupload']?? But you never read that file, do you? This $file_field="@$file[tmp_name]"; should be $file_field = file_get_contents($file['tmp_name']); or am I just too confused? ;-) Commented Jul 5, 2011 at 17:35

2 Answers 2

2

CURL can accept a raw array of key=>value pairs for POST fields. There's no need to do all that urlencode() and http_build_query() stuff. Most likely the @ in the array is being mangled into %40, so CURL doesn't see it as a file upload attempt.

$fields = array(
    'mediaupload'=>$file_field,
    'username'=> $_POST["username"),
    etc...

curl_setopt($ch,CURLOPT_POSTFIELDS,$fields);
Sign up to request clarification or add additional context in comments.

1 Comment

Passing the value of $_POST["username"] directly to the CURLOPT_POSTFIELDS data opens you up to an attack where "@/path/to/file" is specified by the browser in the "username" field. That will allow browser-specified filenames be fetched off the server's hard disk.
1

The http_build_query function generates a URL encoded query string which means that the "@file.ext" is URL encoded in the output as a string and cURL doesn't know that you're trying to upload a file.

My advice would be not to include the file to upload in the http_build_query call and included manually in the CURLOPT_POSTFIELDS.

$file = $_FILES['mediaupload'];
$file_field="@$file[tmp_name]";
$fields = array(
    'username'=>urlencode($_POST["username"]),
    'password'=>urlencode($_POST["password"]),
    'latitude'=>urlencode($_POST["latitude"]),
    'longitude'=>urlencode($_POST["longitude"]),
    'datetime'=>urlencode($_POST["datetime"]),
    'category'=>urlencode($_POST["category"]),
    'metacategory'=>urlencode($_POST["metacategory"]),
    'caption'=>urlencode($_POST["description"])
);
$fields_string = http_build_query($fields);
echo 'FIELDS STRING: ' . $fields_string;
$url = 'https://www.cyclestreets.net/api/addphoto.json?key=$key';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, 'mediaupload=' . $file_field . '&' . $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec ($ch);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.