OK, I'm using the GoToTraining API to try to create a new Training. The docs say to "post" JSON to the endpoint.
So I have my array of data in PHP (this is a WordPress site, and here I'm grabbing stuff from Advanced Custom Fields data)
$my_data_array = array(
'name' => get_the_title( $_POST['acf']['field_5ab508b853122'] ),
'description' => $_POST['acf']['field_5ab50b2406457'],
'timeZone' => 'America/Los_Angeles',
'times' => array(
array(
'startDate' => date( 'Y-m-d', strtotime( $_POST['acf']['field_5ab50908347ef'] ) ) . 'T' . $_POST['acf']['field_5ab50bc6af8df'] . 'Z',
'endDate' => date( 'Y-m-d', strtotime( $_POST['acf']['field_5ab50908347ef'] ) ) . 'T' . $_POST['acf']['field_5abbd96c6ff8d'] . 'Z',
),
),
'registrationSettings' => array(
'disableConfirmationEmail' => false,
'disableWebRegistration' => true,
)
);
and then I'm just doing:
$payload = json_encode( $my_data_array )
to create the payload, which looks like this, if I print_r the value of $payload:
{"name":"Today’s Class","description":"We can add some default content here","timeZone":"America\/Los_Angeles","times":[{"startDate":"2018-04-24T06:00:00Z","endDate":"2018-04-24T09:00:00Z"}],"registrationSettings":{"disableConfirmationEmail":false,"disableWebRegistration":true}}
If I make the curl request, posting $payload, I get back:
Array
(
[errorCode] => InternalError
[description] => We have encountered an internal error. The request may
be retried, but it may have the same result.
[incident] => 5102160953111715072
)
Could be lots of things, right? But here is thing that's driving me crazy:
If cut and paste that dumped value of $payload above into the "body" field in the sandbox thing on the API reference page (see the link above), it works fine and I get an ID for the new Training back as the response.
Moreover, if I cut and paste that same string and just hardcode it as a string value of my $payload variable in my script (using the exact same code for the curl stuff) -- only difference being I'm hardcoding the value of $payload, like this
$payload = '{"name":"Today’s Class","description":"We can add some default content here","timeZone":"America\/Los_Angeles","times":[{"startDate":"2018-04-24T06:00:00Z","endDate":"2018-04-24T09:00:00Z"}],"registrationSettings":{"disableConfirmationEmail":false,"disableWebRegistration":true}}';
... and make the request that way, it also works and gives me a successful response!
protected function make_request( $url, $method, $fields ) {
// $payload = json_encode( $fields );
$payload = '{"name":"Getting to Know Today’s Electric Utility Industry","description":"We can add some default content here","timeZone":"America\/Los_Angeles","times":[{"startDate":"2018-04-24T06:00:00Z","endDate":"2018-04-24T09:00:00Z"}],"registrationSettings":{"disableConfirmationEmail":false,"disableWebRegistration":true}}';
$http_headers = array(
'Accept: application/json',
'Content-Type: application/json',
'Authorization: OAuth oauth_token=' . $this->access_token,
);
$ch = curl_init();
if ( 'post' == $method ) {
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload ); // define what you want to post
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); // return the output in string format
curl_setopt( $ch, CURLOPT_HTTPHEADER, $http_headers );
}
$response = curl_exec( $ch );
curl_close( $ch ); // close curl handle
return $response;
}
But what's assigned to $payload here is exactly the same thing I'm getting if I print_r what json_encode() returns. Whaa??
I do notice, if I run
mb_detect_encoding( $payload );
I get 'ASCII' from the json_encode version and I get 'UTF-8' on the version where I hardcode the string as the value of the variable. Would that make any difference?
Am I missing something simple? Anyone have any idea what I might be doing wrong here? Been beating my head against the wall for too many hours.
So for posterity: Turns out that apostrophe in the name of the Training was causing GTT to choke on the data getting sent over. But it had something to do with the get_the_title() function, which handles apostrophes and quotes differently than just grabbing the value from $post->post_title. When I changed the code that was assembling the data for the API call to $post->post_title instead of get_the_title(), it worked.
Related
I've implemented everything up through Creating a Signature. I created a function to collect the required parameters (I've added some comments here for clarity):
function collect_parameters(){
global $credentials; // This is an Object with my App's credentials and stuff
$oAuth = get_user_oauth(); // This returns an object with the the personal user OAuth tokens retrieved from the earlier docs.
$encoded_collection = array();
$collection = array(
'status' => rawurlencode( $_GET['tweet'] ),
'include_entities' => 'true',
'oauth_consumer_key' => $credentials->key,
'oauth_nonce' => $credentials->nonce, // md5( str_shuffle( uniqid() . mt_rand(0,9999999999) ) )
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => $credentials->time, // current timestamp
'oauth_token' => $oAuth->oauth_token,
'oauth_version' => '1.0',
);
// Percent encode every key and value that will be signed.
foreach( $collection as $key => $value ){
$encoded_collection[rawurlencode($key)] = rawurlencode($value);
}
// Sort the list of parameters alphabetically by encoded key.
ksort( $encoded_collection );
return http_build_query( $encoded_collection );
}
I use this function to build the Signature Base String
function create_signature_base_string( $parameter_string, $url = 'https://api.twitter.com/1.1/statuses/update.json', $method = 'POST' ){
return strtoupper( $method ) .'&'. rawurlencode( $url ) .'&'. rawurlencode( $parameter_string );
}
I use this function to calculate the signature
function calculate_signature( $signature_base_string, $signing_key ){
return base64_encode( hash_hmac('sha1', $signature_base_string, $signing_key, true) );
}
Now to building the OAuth Header. here's a function for it, that uses the helper functions from above (plus some others that return the required information):
function get_oauth_headers(){
global $credentials;
$oAuth = get_user_oauth();
$parameters = collect_parameters();
$signature_base_string = create_signature_base_string( $parameters );
$signing_key = get_signing_key();
$signature = calculate_signature( $signature_base_string, $signing_key );
$auth_array = array(
'oauth_consumer_key' => $credentials->key,
'oauth_nonce' => $credentials->nonce,
'oauth_signature' => $signature,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => $credentials->time,
'oauth_token' => $oAuth->oauth_token,
'oauth_version' => '1.0'
);
ksort( $auth_array );
return $auth_array;
}
Now I've got everything in a nice & neat little array, it's time to actually try and send this to Twitter.
function create_tweet( $build_query = true ){
global $credentials;
$ch = curl_init();
$url = 'https://api.twitter.com/1.1/statuses/update.json';
$fields = array(
'status' => rawurlencode( $_GET['tweet'] ) // I've just been using "Test" or "WhyNoWork" style text in this $_GET param
);
$oAuth_headers = get_oauth_headers(); // This uses that function above that returns all of the specific parameters for OAuth, sorted, and ready to go.
$oAuth_array = array();
// Loop through the oauth headers, and encode them
foreach( $oAuth_headers as $key => $value ){
$oAuth_array[] = rawurlencode($key) .'="'. rawurlencode($value) .'"';
}
// Implode it into a single line
$oAuth_string = implode(', ', $oAuth_array );
$headers = array(
'Content-Type: application/x-www-form-rawurlencoded',
'Authorization: OAuth '. $oAuth_string,
);
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_ENCODING, 'gzip' );
curl_setopt( $ch, CURLOPT_POST, true );
// It seems to prefer this as a query string instead of postfields?
if( $build_query == true ){
curl_setopt( $ch, CURLOPT_URL, $url.'?'.http_build_query($fields) );
} else {
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $fields );
}
$result = curl_exec( $ch );
$info = curl_getinfo( $ch );
curl_close( $ch );
if( isset($_GET['debug']) ){
echo $result;
var_dump( $info );
} else {
echo $result;
}
}
For example, here's the order of everything in the OAuth header. I've run through each of my little helper functions a dozen times making sure they take in the right arguments and output the appropriate values. I've even replaced my own OAuth credentials with the ones from the docs, and end up with the same results they do for the signing key, signature, etc.:
Yet, everytime I try and run the create_tweet() function, I get a 401 status code with error 32: {"errors":[{"code":32,"message":"Could not authenticate you."}]}. What the heck am I missing? Is it possible to see why they couldn't authenticate the request?
Here's the output from collect_parameters();
include_entities=true&oauth_consumer_key=APP_API_KEY&oauth_nonce=ABC123&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1597456781&oauth_token=USER_AUTH_TOKEN&oauth_version=1.0&status=TESTING
That is passed to the Signature Base String function, which returns the following:
POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3DAPP_API_KEY%26oauth_nonce%3DABC123%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1597457034%26oauth_token%3DUSER_AUTH_TOKEN%26oauth_version%3D1.0%26status%3DTESTING
That looks good, and now I take the signing key: APP_SECRET&USER_AUTH_SECRET and pass those to calculate the signature gives me a value just like the one in the Docs (and using the params in the docs gives me the same signature that they show): thIsiSeEmSUnNecEssArYPOs3OxQdSNpI=
I don't understand how I can replace my data with the test data and get the same result, but I still can't get an API Request authenticated?
You are performing a couple of extra encodings.
First, in collect_parameters you are encoding keys and values for the $encoded_collection array and then passing that to http_build_query which will further encode them. You can completely remove the loop to encode items and instead pass them directly to http_build_query. The trick there is that it defaults to + encoding, so you need to tell it to switch to % encoding using the fourth parameter:
function collect_parameters()
{
global $credentials; // This is an Object with my App's credentials and stuff
$oAuth = get_user_oauth(); // This returns an object with the the personal user OAuth tokens retrieved from the earlier docs.
$collection = [
'status' => 'Hello Ladies + Gentlemen, a signed OAuth request!',
'include_entities' => 'true',
'oauth_consumer_key' => $credentials->key,
'oauth_nonce' => $credentials->nonce, // md5( str_shuffle( uniqid() . mt_rand(0,9999999999) ) )
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => $credentials->time, // current timestamp
'oauth_token' => $oAuth->oauth_token,
'oauth_version' => '1.0',
];
// Sort the list of parameters alphabetically by encoded key.
ksort($collection);
return http_build_query($collection, '', '&', PHP_QUERY_RFC3986);
}
Next, in your create_tweet function, in the first loop, you are encoding both keys and values again which isn't needed and can be removed:
foreach ($oAuth_headers as $key => $value) {
$oAuth_array[] = $key . '="' . $value . '"';
}
I unfortunately don't have a Twitter account to test all of this, but their docs have sample keys that I was able to use and a sample output, and using that these changes and the docs produced the same output.
I am having the following code to make a GET statement to the REST API of Parse server using PHP:
$query = json_encode(
array(
'where' => array( 'userid' => "8728792347239" )
));
echo $query;
$ch = curl_init('https://*hidden*.herokuapp.com/parse/classes/computers?'.$query);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'X-Parse-Application-Id: *hidden*',
'X-Parse-REST-API-Key: *hidden*',
'Content-Type: application/json'
)
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
print_r($response);
However I am getting the following error:
{"code":102,"error":"Invalid parameter for query: {\"where\":{\"userid\":\"8728792347239\"}}"}
What am I doing wrong?
without having read the documentation, i bet it's supposed to be url-encoded, not json-encoded -OR- that the data is supposed to be in the POST body, not the URL query.
if guess #1 is correct, then your problem is that you're using json_encode instead of http_build_query eg
$query = http_build_query(
array(
'where' => array( 'userid' => "8728792347239" )
));
if guess #2 is correct, then your problem is that you're adding the data to the url query instead of adding it to the request body, eg
$ch = curl_init('https://*hidden*.herokuapp.com/parse/classes/computers');
curl_setopt($ch,CURLOPT_POSTFIELDS,$query);
i have a register page for allow users to register. before register i need to validate their phone number. i have given a web-service address along with its parameters.
the parameters i have given:
http://*********
Method:POST
Headers:Content-Type:application/json
Body:
the following in:
{
"mobileNo":"0*********",
"service":"****",
"Code1":"*****",
"content":"hi",
"actionDate":"2017/09/26",
"requestId":"1"
}
and here the code i found in the Internet:
$data = array(
'mobileNo' => '****',
'service' => '***',
'Code1' => '*****',
'content' => '55',
'actionDate' => '2017/09/26');
$options = array(
'http' => array(
'method' => 'POST',
'content' => json_encode( $data ),
'header'=> "Content-Type: application/json" .
"Accept: application/json"
)
);
$url = "******";
$context = stream_context_create( $options );
$result = file_get_contents( $url, false, $context );
$response = json_decode( $result );
and here is error i face with when i test local:
file_get_contents(http://********/sms-gateway/sms-external-zone /receive): failed to open stream: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
and there is no error and no result(receive SMS) in response when i test online(cpanel server)
According to the given parameters, where do i wrong?
thanks in advance.
According to your Error, it seems your service did not respond. Have you tried to open it in a browser, to check if any response there?
Maybe the service you try to call requires you to provide a Static IP from your Webserver, as they only grant access on a IP based level. Means, your IP is blocked until they allow it.
I suggest you use cURL to do your request. This way you get future data to use for debugging, if anything fails. Still here, if the service does not respond, you want get any other information.
$data = array(
'mobileNo' => '****',
'service' => '***',
'Code1' => '*****',
'content' => '55',
'actionDate' => '2017/09/26');
$url = "******";
$ch = curl_init( $url );
// set data as json string
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($data));
// define json as content type
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
// tell curl to fetch return data
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// follow location if redirect happens like http to https
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
// send request
$result = curl_exec($ch);
// gives you the result - most of the time you only want this
var_dump($result);
// for debugging purpose, gives you the whole connection info
var_dump(curl_getinfo($ch));
// gives back any occurred errors
var_dump(curl_error($ch));
curl_close($ch);
Edit: I added the CURLOPT_FOLLOWLOCATION, as a request may gets redirected. We want to catch that as well. And I added the curl_close at the end. If it is closed, error or info data can be fetched.
I hope my question will be understood, my english is a not so good.
I'm nearly new with PHP and I just discovered REST APIs: I'm trying to use a REST API from my PHP script. Docs for the API can be found here
My final goal is to get a single product from this webservice and update it by adding the wholesalePrices array.
I've already managed to perform a GET request using file_get_contents(), in order to get the product ID i want to update. Now I have such id but can't understand how to perform the PUT request: as far I can understand, there are mainly two ways to do REST calls in PHP: one with file_get_contents, another by using cURL.
Since I used file_get_contents for my GET request, I continued with this approach, but my code:
$wholesalePrices = json_encode($wholesalePrices);
$dataRAW = array(
"wholesalePrices" => $wholesalePrices
);
$dataToPut = http_build_query($dataRAW);
$context = [
'http' => [
'method' => 'PUT',
'header' => "Authorization: apikeystring\r\n" . "Content-Length: " . strlen($dataToPut) . "\r\n" . "Content-Type: application/json\r\n",
'content' => $dataToPut
]
];
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode(myToken);
$result = file_get_contents ($url, false, $context);
returns a PHP warning:
Warning: file_get_contents(https://app.ecwid.com/api/v3/xxxxxxxxx/products/xxxxxxxxx?token=xxxxxxxxxxx): failed to open stream: HTTP request failed! HTTP/1.1 400 Wrong JSON format: A JSONObject text must begin with '{' at 1 [character 2 line 1] in upload.php on line 95
var_dumping $wholesalePrices just after the json_encode() results in
string '[{"quantity":1,"price":0},{"quantity":5,"price":6},{"quantity":25,"price":12},{"quantity":100,"price":25}]' (length=106)
where am I wrong?
ok, I tried using RamRaider approach and now my code is this
$data = json_encode(array('wholesalePrices' => $wholesalePrices)/*, JSON_FORCE_OBJECT*/);
$dataRAW = array(
"wholesalePrices" => $wholesalePrices
);
$dataToPut = $dataRAW;
$dataToPut = http_build_query($dataRAW);
$context = array('http' => array('method' => 'PUT',
'header' => "Authorization: apikeystring\r\nContent-Length: ".strlen($data)."\r\nContent-Type: application/json\r\n",
'content' => $data));
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/".urlencode(MY_STORE_ID)."/products/".urlencode($productId)."?token=".urlencode(MY_TOKEN);
$result = file_get_contents ($url, false, $context);
But I obtain a HTTP request failed! HTTP/1.1 400 Field Product.wholesalePrices should be an array message.
If I comment the , JSON_FORCE_OBJECT instead, the HTTP message becomes 409 Conflict and it refers at the line with $result = file_get_contents ($url, false, $context); so perhaps I am on the right track, but how can I troubleshoot such error?
ok, done some mods: now - after the json_encode() - my dataToPut (which I put in "Content" in the HTTP request) var_dumps as following (WPPair is a class I specifically created to reproduce the format required):
object(stdClass)[3]
public 'wholesalePrices' =>
array (size=3)
1 =>
object(WPpair)[5]
public 'quantity' => int 5
public 'price' => int 6
2 =>
object(WPpair)[4]
public 'quantity' => int 25
public 'price' => int 12
3 =>
object(WPpair)[6]
public 'quantity' => int 100
public 'price' => int 25
so I think it has to be right for the api. But I still get a HTTP request failed! HTTP/1.1 400 Bad Request
Ok, finally I managed to form a (perhaps) right structure for my JSON, all the more so as Postman validates my dataToPut with an HTTP
200 OK
And my test record results updated.
This is the print_r() output on dataToPut after json_encode():
string
'{"id":56782231,"wholesalePrices":[{"quantity":5,"price":5.64},{"quantity":25,"price":5.28},{"quantity":100,"price":4.5}]}'
(length=121)
However, if I try to send the same JSON from my PHP page, I still get a
failed to open stream: HTTP request failed!
and in fact, my records still aren't updated.
Here's my code:
$dataToPut = $dataRAW;
$dataRAW = http_build_query($dataRAW);
$context = [
'http' => [
'method' => 'PUT',
'header' => "Authorization: apikeystring\r\n" . "Content-Length: ".sizeof($dataToPut)."\r\n" . "Content-Type: application/json\r\n",
'content' => $dataToPut
]
];
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode(myToken);
$dataToPut = json_encode($dataToPut);
$result = file_get_contents($url, false, $context);
Where am I wrong this time?
After rewriting my code by using cURL instead of file_get_contents to connect to the API, I managed to get it to work.
Now the API call part looks like this:
$dataToPut = $dataRAW;
$dataRAW = http_build_query($dataRAW);
$context = [
'http' => [
'method' => 'PUT',
'header' => "Authorization: apikeystring\r\n" . "Content-Length: ".sizeof($dataToPut)."\r\n" . "Content-Type: application/json\r\n",
'content' => $dataToPut
]
];
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode($myToken);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Host: app.ecwid.com','Content-Type: application/json;charset=utf-8','Cache-Control: no-cache'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $dataToPut);
// Make the REST call, returning the result
$response = curl_exec($curl);
echo ($response."<br/>");
if (!$response) {
echo("Connection Failure: ".curl_error($curl));
die();
}
curl_close($curl);
Without seeing the documentation for their api I might be leading you astray but the error message does suggest that their api expects json data whereas you encode the data and then add to an array which seems back to front somehow.
$data = json_encode( array( 'wholesalePrices' => $wholesalePrices ), JSON_FORCE_OBJECT );
/* Perhaps this also is not required */
#$data = http_build_query( $data );
$context = array(
'http' => array(
'method' => 'PUT',
'header' => "Authorization: apikeystring\r\nContent-Length: " . strlen( $data ) . "\r\nContent-Type: application/json\r\n",
'content' => $data
)
);
$context = stream_context_create( $context );
$url = "https://app.ecwid.com/api/v3/7560546/products/".urlencode( $productId )."?token=".urlencode( myToken );
$result = file_get_contents( $url, false, $context );
Having had a quick look at the api documentation I found the following:
PUT https://app.ecwid.com/api/v3/{storeId}/products/{productId}?token={token}
Request body
A JSON object of type 'Product’ with the following fields:
wholesalePrices -> Array<WholesalePrice>
described as: "Sorted array of wholesale price tiers (quantity limit and price pairs)"
The given example request to update a product is:
PUT /api/v3/4870020/products/39766764?token=123456789abcd HTTP/1.1
Host: app.ecwid.com
Content-Type: application/json;charset=utf-8
Cache-Control: no-cache
{
"compareToPrice": 24.99,
"categoryIds": [
9691094
]
}
So using test data
$wholesalePrices=array(
array('quantity'=>10,'price'=>1000),
array('quantity'=>2,'price'=>43),
array('quantity'=>43,'price'=>34),
array('quantity'=>7,'price'=>5),
array('quantity'=>9,'price'=>63),
);
$data = json_encode( array( 'wholesalePrices' => $wholesalePrices ) );
echo '<pre>',$data,'</pre>';
Gives data in the format:
{
"wholesalePrices":[
{"quantity":10,"price":1000},
{"quantity":2,"price":43},
{"quantity":43,"price":34},
{"quantity":7,"price":5},
{"quantity":9,"price":63}
]
}
I am going to convert some file using php and send it as a part of HTTP POST request.
There is part of my code:
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: " . $this->contentType."",
'content' => "file=".$file
)
));
$data = file_get_contents($this->url, false, $context);
Does variable $file have to be byte representation of the file which I want to send?
And is that correct way to send file in php without using form? Have you got any clues?
Also what is the way to convert file to byte representation using PHP?
You may find it much easier to use CURL, for example:
function curlPost($url,$file) {
$ch = curl_init();
if (!is_resource($ch)) return false;
curl_setopt( $ch , CURLOPT_SSL_VERIFYPEER , 0 );
curl_setopt( $ch , CURLOPT_FOLLOWLOCATION , 0 );
curl_setopt( $ch , CURLOPT_URL , $url );
curl_setopt( $ch , CURLOPT_POST , 1 );
curl_setopt( $ch , CURLOPT_POSTFIELDS , '#' . $file );
curl_setopt( $ch , CURLOPT_RETURNTRANSFER , 1 );
curl_setopt( $ch , CURLOPT_VERBOSE , 0 );
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
Where $url is where you want to post to, and $file is the path to the file you want to send.
Oddly enough I just wrote an article and illustrated this same scenario. (phpmaster.com/5-inspiring-and-useful-php-snippets). But to get you started, here's code that should work:
<?php
$context = stream_context_create(array(
"http" => array(
"method" => "POST",
"header" => "Content-Type: multipart/form-data; boundary=--foo\r\n",
"content" => "--foo\r\n"
. "Content-Disposition: form-data; name=\"myFile\"; filename=\"image.jpg\"\r\n"
. "Content-Type: image/jpeg\r\n\r\n"
. file_get_contents("image.jpg") . "\r\n"
. "--foo--"
)
));
$html = file_get_contents("http://example.com/upload.php", false, $context);
In situations like these it helps to make a mock web form and run it through Firefox with firebug enabled or something, and then inspect the request that was sent. From there you can deduce the important things to include.