I'm trying to send a multipart/form-data form to a REST API. It should be possible to send files, but the other POST fields should be delivered as JSON.
That's how it should look like:
---------------------------acebdf13572468
Content-Disposition: form-data; name=entity
Content-Type: application/json
{
"vacancyId": "xxx",
"locationId": xxx,
"salutationId": xxx,
"firstname": "xxx",
"lastname": "xxx",
"xingProfile": "xxx",
"mobileNumber": "xxx",
"emailAddress": "xxx",
"comment": "xxx",
"mediaOptionId": xxx
}
---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="Archive.zip"
Content-Type: application/x-zip-compressed
<#INCLUDE *xxx\Archive.zip*#>
---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="CV.pdf"
Content-Type: application/octet-stream
<#INCLUDE *xxx\CV.pdf*
---------------------------acebdf13572468--
I'm trying to solve this with PHP curl.
This is the current code for it:
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: ' . $contentType));
curl_setopt($curl, CURLOPT_POST, 1);
// ...
$data = json_decode($data, true); // data comes as JSON string
$tmpData = $data;
$tmpData['file'] = null; // remove files
$tmpData = (object) array_filter((array) $tmpData); // filter empty values
$json = json_encode($tmpData); // generate JSON entity
// generate data for posting
$postData = array();
$postData['entity'] = 'Content-Type: application/json\r\n\r\n' . $json;
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type' => 'multipart/form-data'));
// go through uploaded files
for ($i = 0; $i < count($data['file']); $i++) {
$file = $data['file'][$i];
$uploadedFile = curl_file_create($file['tmp_name'], $file['type'], $file['name']);
$postData['file'] = $uploadedFile;
}
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
The request looks ok for me, but for some reason the API is not able to parse the JSON. I'm pretty sure it's because of Content-Type: application/json, which doesn't work like this. But maybe it's another problem. Any ideas?
This is the request, which the API gets:
: --------------------------259e507e48ab52a4
Content-Disposition: form-data; name="entity"
Content-Type: application/json\r\n\r\n{"vacancyId":xxx,"locationId":xxx,"salutationId":xxx,"firstname":"xxx","lastname":"xxx","emailAddress":"xxx","mobileNumber":"xxxx","comment":"xxx","mediaOptionId":xxxx,"xingProfile":"xxx"}
--------------------------259e507e48ab52a4--
PS: Files can be ignored for now. It seems to be a problem with the JSON part.
Related
Am trying to create session for uploading files to google drive via resumable upload
API source
https://developers.google.com/drive/api/v3/manage-uploads#resumable
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/jpeg
X-Upload-Content-Length: 2000000
{
"name": "myObject"
}
Here is the definition of what all the http headers does.
X-Upload-Content-Type. Optional. Set to the MIME type of the file data, which will be transferred in subsequent requests.
If the MIME type of the data is not specified in metadata or through this header, the object will be served as
application/octet-stream.
X-Upload-Content-Length. Optional. Set to the number of bytes of file data, which will be transferred in subsequent requests.
Content-Type. Required if you have metadata for the file. Set to application/json; charset=UTF-8.
Content-Length. Required unless you use chunked transfer encoding. Set to the number of bytes in the body of this initial
request.
Here is my code.
My issue is that the code will keeps on loading on the browser until it times out.
I have increased max_exection time
severally but the same issue. I was wondering what I have done wrong with the curl headers or the codes itself..
ini_set('max_execution_time', 3000);
$url= 'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable';
$token='my token goes here';
$file_name = "nancy.zip";
echo $fsize =filesize($file_name);
$mType='application/zip';
echo $chunkSize = 1 * 1024 * 1024; // 1mb
$datas = '{
"name": "'.$file_name.'"
}';
/*
$header=array(
//"Host: www.googleapis.com",
"Authorization: Bearer $token",
"Content-Length: $chunkSize",
"Content-Type: application/json; charset=UTF-8",
"X-Upload-Content-Type: $mType",
"X-Upload-Content-Length: $fsize"
);
*/
//ziganotschka suggestions
$header=array(
"Authorization: Bearer".$token,
"Content-Length: ".$chunkSize,
"Content-Type: application/json; charset=UTF-8",
"X-Upload-Content-Type:".$mType,
"X-Upload-Content-Length: ".$fsize );
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_CUSTOMREQUEST,'POST');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch,CURLOPT_POSTFIELDS, $datas);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$res = curl_exec($ch);
curl_close($ch);
var_dump($res);
So I'm trying to mime the following:
------WebKitFormBoundarygLmTBM5HATvn9tpA
Content-Disposition: form-data; name="name"
p1bieoilebde1ra71v4tm2rlb3h.png
------WebKitFormBoundarygLmTBM5HATvn9tpA
Content-Disposition: form-data; name="file"; filename="watch.png"
Content-Type: image/png
------WebKitFormBoundarygLmTBM5HATvn9tpA--
My code looks like this
$cfile = new CURLFile(realpath(dirname(__FILE__) . "/../images/watch.png"));
$to_post = array ('file' => $cfile);
curl_setopt($ch, CURLOPT_POSTFIELDS, $to_post);
And it's not working, any help?
Recently I work with an API that require send the data in JSON-RPC format.
And I construct like that
function create_video($files) {
$api = "http://api.brightcove.com/services/post";
$local_file_list = $files['file']['tmp_name'];
foreach ($local_file_list as $local_file) {
try {
$ch = curl_init();
if (FALSE === $ch) {
throw new Exception('failed to initialize');
}
$params = array(
"encode_to" => "MP4",
"create_multiple_renditions" => "True",
"token" => WRITE_TOKEN,
"file" => #$local_file
);
$request = json_encode(array('jsonrpc' => '2.0', 'method' => 'create_video', 'params' => $params));
curl_setopt($ch, CURLOPT_URL, $api);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
if (FALSE === $content) {
throw new Exception(curl_error($ch), curl_errno($ch));
}
die(var_dump(json_decode($content)));
return json_decode($content);
} catch (Exception $e) {
trigger_error(sprintf('Curl failed with error #%d: %s', $e->getCode(), $e->getMessage()), E_USER_ERROR);
}
}
}
The problem is , it create the incorrect json structure comparing to the correct one.
Request Payload of my version
------WebKitFormBoundary8VABz8KuNRE8Hepd
Content-Disposition: form-data; name="file[0]"; filename="big_buck_bunny.mp4"
Content-Type: video/mp4
------WebKitFormBoundary8VABz8KuNRE8Hepd--
Request Payload of correct version
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="JSONRPC"
{"params":{"video":{"name":"test","shortDescription":"test","startDate":1432282741000,"endDate":null},"encode_to":"MP4","create_multiple_renditions":"True","token":"VyocgALDnxU8HPvmnSnckgmXjoPlYWomc2La5Tn-evuAfsnSPJJoow.."},"method":"create_video"}
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="filePath"; filename="big_buck_bunny.mp4"
Content-Type: video/mp4
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="JSONView"
{"params":{"video":{"name":"test","shortDescription":"test","startDate":1432282741000,"endDate":null},"encode_to":"MP4","create_multiple_renditions":"True","token":"VyocgALDnxU8HPvmnSnckgmXjoPlYWomc2La5Tn-evuAfsnSPJJoow.."},"method":"create_video"}
------WebKitFormBoundaryCAB6WEANBJxoB3Op--
And the correct website that send data, you may enter the form to test
http://docs.brightcove.com/en/video-cloud/media/samples/create_video.html#request
And the API reference(create video)
https://docs.brightcove.com/en/video-cloud/media/references/reference.html#Video_Write
Thanks a lot for helping.
The documentation of their API reference (the second link) states:
For write requests, he data submitted to the media write API should be
in JSON format, encoded as a form parameter named "json". The JSON
document should include a "method" field and a "params" field, and the
examples you publish should show the whole body of the POST request:
json=
So, just replace:
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
with:
curl_setopt($ch, CURLOPT_POSTFIELDS, 'json=' . $request);
and it should be working then. I got error "invalid token" instead of "Could not find JSON-RPC." by replacing the code above.
I guess I'd like to know if it is possible POST multipart/data-form content type containing json, files, txt, xml in the same post.
so request would look like this:
Content-Type: multipart/form-data; boundary=BOUNDARY
--BOUNDARY
Content-type:application/json
Content-Disposition:form-data
{{"SomeJsonObject":"valueOfObject"}}
--BOUNDARY
Content-type:application/xml
Content-Disposition:form-data
<node>SomeXML Nodes</node>
--BOUNDARY--
I know I can code this as a string, include boundaries manually, but I want to know if it is possible via
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
Thank you
You can pass Content-Type to each multipart boundary with this hack also:
$url = 'https://...'
$data = ["json\";\nContent-type:\"application/json\";\nContent-disposition:\"form-data" => '{"my":json}',
"xml\";\nContent-type:\"application/xml\";\nContent-disposition:\"form-data" => "<root/>"];
$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, $url);
curl_setopt($resource, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($resource, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($resource);
curl_close($resource);
The idea is to 'inject' all necessary headers to "name" option, like in SQL injection.
The code above will send multipart request with all necessary headers:
------------------------------b66e31048210
Content-Disposition: form-data; name="json";
Content-type:"application/json";
Content-disposition:"form-data"
{"my":json}
------------------------------b66e31048210
Content-Disposition: form-data; name="xml";
Content-type:"application/xml";
Content-disposition:"form-data"
<root/>
But be careful, this stuff is very bad documented.
there is no way to post STRING data in POST except building boundary yourself but curl can post files from disk so
file_put_contents('/tmp/fileForSend.json');
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
'file' =? '#/tmp/fileForSend.json;type=application/json', // this is CURL integrared feature, curl will read file itself
));
so putting '#' sybmol means for CURL that it must read file and put its content into POST request
I am trying to upoad attachments to a specific case using REST API which I have successfully completed.
the files are being uploaded to that specific case. and I am using base64_encode to send binary data to SalesForce as they required the binary data to be sent.
but the issue is that when I see the files in the sales force control panel,
all the files are listed there and their size is correct, name is correct etc
but when I view/download any file uploaded with the script it doesn't open. the file shows errror.
ie. when I upload an png image with the rest API, I wont be able to open the image after downloading from the sales force control panel.
Can any one please help?
I think sales force might not decode the uploaded files back from base64_encode, is that right?
Thanks in advance
here is the code
$fp = fopen($file, 'r');
$db_img = fread($fp, filesize($file));
$db_img = addslashes($db_img);
$db_img = base64_encode($db_img);
and then after encoding I am concatenating $db_img within the body element like this
...................
...'.$db_img.'...
.................;
I figured it out myself. I thought I should post the answer as well. I am using the following function to add attachments to the Case Object.
No need to convert to base64 at all
public function add_attachment($case_id, $full_file_path, $file_name) {
$url = $this->instance_url."/services/data/v33.0/chatter/feed-elements";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
$headers = array();
$headers[] = "Authorization: OAuth $this->access_token";
$headers[] = 'Content-Type: multipart/form-data; boundary=a7V4kRcFA8E79pivMuV2tukQ85cmNKeoEgJgq';
$post_text = '--a7V4kRcFA8E79pivMuV2tukQ85cmNKeoEgJgq
Content-Disposition: form-data; name="json"
Content-Type: application/json; charset=UTF-8
{
"body":{
"messageSegments":[
{
"type":"Text",
"text":"Task Attachment"
}
]
},
"capabilities":{
"content":{
"description":"Task Attachment",
"title":"'.$file_name.'"
}
},
"feedElementType":"FeedItem",
"subjectId":"'.$case_id.'"
}
--a7V4kRcFA8E79pivMuV2tukQ85cmNKeoEgJgq
Content-Disposition: form-data; name="feedElementFileUpload"; filename="'.$file_name.'"
Content-Type: image/png
'. file_get_contents($full_file_path).'
--a7V4kRcFA8E79pivMuV2tukQ85cmNKeoEgJgq--';
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_text);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
$response_json = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
//print_r($info);
if ( $status != 201 ) {
$this->errors[] = "Error: call to URL $url failed with status $status, response $json_response, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl);
return FALSE;
}
$this->status = $status;
$this->curl_error = curl_error($curl);
$this->curl_errno = curl_errno($curl);
return json_decode($response_json,TRUE);
}