CURL: Send images with boundary to REST API - php

Im currently working with some kind of API. I have wrote simple functions which allows me to add new content, however Im stuck on uploading images.
Here's simple CURL command in documentation:
curl -v -s -u username:password \
-H "Content-Type: multipart/form-data" \
-H "Accept: application/api+json" \
-F "image=#img1.jpeg;type=image/jpeg" \
-F "image=#img2.jpeg;type=image/jpeg" \
-XPUT ''
And a sample REQUEST:
PUT /images HTTP/1.1
Host: example
Content-Type: multipart/form-data; boundary=vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx
--vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx
Content-Disposition: form-data; name="image"; filename="img1.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Now, there is my function:
$headers_put = array(
"Content-Type: multipart/form-data; boundary=vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx",
"Accept: application/+json",
);
function putImages($ch, $headers, $ad, $images){
$url = '/images';
$files = [];
foreach($images as $key => $image) {
$number = $key +1;
$paths = parse_url($image, PHP_URL_PATH);
$paths = $_SERVER['DOCUMENT_ROOT'] . $paths;
$cfile = new CURLFile(''. $paths, 'image/jpeg', 'image'.$key);
$files[$key] = $cfile;
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $files);
$result = curl_exec($ch);
var_dump($result);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "\n";
}
Finally, the response is:
{"errors":{"error":{"#key":"unsupported-form-element"}}}"
What Im doing wrong? Any ideas? Thank you kindly for any help.

After several approaches using curl_file_create without getting it to work. I think the mobile.de-API is just implemented badly.
I ended up implementing a custom routine for CURLOPT_POSTFIELDS that is creating the complete multipart manually. I borrowed most of the code from the PHP manpage as "The CURLFile class".
Create an array of the filenames
Create multipart header (see code below)
function curl_custom_postfields(array $files = array()) {
// build file parameters
foreach ($files as $k => $v) {
switch (true) {
case false === $v = realpath(filter_var($v)):
case !is_file($v):
case !is_readable($v):
continue; // or return false, throw new InvalidArgumentException
}
$data = file_get_contents($v);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"image\"",
"Content-Type: image/jpeg",
"",
$data,
));
}
// generate safe boundary
do {
$boundary = "---------------------" . md5(mt_rand() . microtime());
} while (preg_grep("/{$boundary}/", $body));
// add boundary for each parameters
array_walk($body, function (&$part) use ($boundary) {
$part = "--{$boundary}\r\n{$part}";
});
// add final boundary
$body[] = "--{$boundary}--";
$body[] = "";
// set options
return array(implode("\r\n", $body), $boundary);
}
Use that function ;)
$postfields = $this->curl_custom_postfields($files);
Add boundary to http header
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data; boundary=' . $postfields[1], 'Accept: application/vnd.de.mobile.api+json'));
Add Postfields
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields[0]);
It's not the cleanest solution at all so please use it with care. But at least it works.

I have the same problem and found a solution but only for single images.
The trick is that your array MUST look like these:
$images = array(
'image' => 'PATH/IMG.jpg',
);
That means that the the key must be "image" and nothing other!
I hope that helps ;)

Related

Telegram BOT Api: how to send a photo using PHP?

The sendPhoto command require an argument photo defined as InputFile or String.
The API doc tells:
Photo to send. You can either pass a file_id as String to resend a photo
that is already on the Telegram servers, or upload a new photo using
multipart/form-data.
And
InputFile
This object represents the contents of a file to be uploaded. Must be
posted using multipart/form-data in the usual way that files are
uploaded via the browser.
So I tried this method
$bot_url = "https://api.telegram.org/bot<bot_id>/";
$url = $bot_url . "sendPhoto?chat_id=" . $chat_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type:multipart/form-data"
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
"photo" => "#/path/to/image.png",
));
curl_setopt($ch, CURLOPT_INFILESIZE, filesize("/root/dev/fe_new.png"));
$output = curl_exec($ch);
The curls is executed, but Telegram reply this to me:
Error: Bad Request: Wrong persistent file_id specified: contains wrong
characters or have wrong length
I also tried replacing #/path... with a file_get_contents, but in this case Telegram give me an empty reply (and curl_error is empty !).
What the way to send a photo to telegram using php + curl ?
This is my working solution, but it requires PHP 5.5:
$bot_url = "https://api.telegram.org/bot<bot_id>/";
$url = $bot_url . "sendPhoto?chat_id=" . $chat_id ;
$post_fields = array('chat_id' => $chat_id,
'photo' => new CURLFile(realpath("/path/to/image.png"))
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type:multipart/form-data"
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
$output = curl_exec($ch);
This code helps me alot which I get from php.net website here
Visit http://php.net/manual/en/class.curlfile.php#115161
(Vote Up this code in php website).
I just change headers in this code for telegram bot to send image just copy this function
function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) {
// invalid characters for "name" and "filename"
static $disallow = array("\0", "\"", "\r", "\n");
// build normal parameters
foreach ($assoc as $k => $v) {
$k = str_replace($disallow, "_", $k);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$k}\"",
"",
filter_var($v),
));
}
// build file parameters
foreach ($files as $k => $v) {
switch (true) {
case false === $v = realpath(filter_var($v)):
case !is_file($v):
case !is_readable($v):
continue; // or return false, throw new InvalidArgumentException
}
$data = file_get_contents($v);
$v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v));
$k = str_replace($disallow, "_", $k);
$v = str_replace($disallow, "_", $v);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"",
"Content-Type: image/jpeg",
"",
$data,
));
}
// generate safe boundary
do {
$boundary = "---------------------" . md5(mt_rand() . microtime());
} while (preg_grep("/{$boundary}/", $body));
// add boundary for each parameters
array_walk($body, function (&$part) use ($boundary) {
$part = "--{$boundary}\r\n{$part}";
});
// add final boundary
$body[] = "--{$boundary}--";
$body[] = "";
// set options
return #curl_setopt_array($ch, array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => implode("\r\n", $body),
CURLOPT_HTTPHEADER => array(
"Expect: 100-continue",
"Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type
),
));
}
Basic Try:Now just use this code by sending photo name with path and chat id
here is it how:-
$array1=array('chat_id'=><here_chat_id>);
$array2=array('photo'=>'index.jpg') //path
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://api.telegram.org/<bot_token>/sendPhoto");
curl_custom_postfields($ch,$array1,$array2);//above custom function
$output=curl_exec($ch);
close($ch);
For sending png or other methods change curl_custom function according to your need.
I searched a lot online but didn't find the answer. But, your question solved my problem ... I just changed your code and that answered it for me ...
I changed your code to this:
$chat_id=chat Id Here;
$bot_url = "https://api.telegram.org/botYOUR_BOT_TOKEN/";
$url = $bot_url . "sendPhoto?chat_id=" . $chat_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type:multipart/form-data"
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
"photo" => "#path/to/image.png",
));
curl_setopt($ch, CURLOPT_INFILESIZE, filesize("path/to/image.png"));
$output = curl_exec($ch);
print$output;
You can use this API: https://github.com/mgp25/Telegram-Bot-API
example:
$tg->sendPhoto($chat_id, $image, $caption);
You can use either a stored image or URL.
<?php
$BASH_Command='curl -s -X POST "https://api.telegram.org/bot<YourToken>/sendPhoto?chat_id=<YourID>" -F photo="#/path/to/imagefile.jpeg" -F caption="TheImage" > /dev/null &';
echo exec($BASH_Command);
?>
This a bad idea, but you can use some like that:
#!/bin/bash
set -x
set -e
BDIR=/tmp/${RANDOM}
TG_TOKEN=""
TG_CHAT_ID=
mkdir -p ${BDIR}
chmod -R 777 ${BDIR}
su postgres -c "pg_dumpall -f ${BDIR}/postgre.sql"
tar czf ${BDIR}/${HOSTNAME}.tar.gz /var/lib/grafana/ /etc/grafana/ ${BDIR}/postgre.sql
curl -F caption="$(date)" -F chat_id="${TG_CHAT_ID}" -F document=#"${BDIR}/${HOSTNAME}.tar.gz" https://api.telegram.org/bot${TG_TOKEN}/sendDocument
rm -rf ${DBIR}
I thought I should extend the answer to include uploading from an external url but it still involves a process of saving the image to a folder first. Then I added a caption to the image.
$bot_url = "https://api.telegram.org/bot<bot_id>/";
$url = $bot_url . "sendPhoto?chat_id=" . $chat_id ;
$caption = 'Telegram Image SendPhoto function';
$img = '/path/to/save_image.png'; //local path where image should be saved
/* Get the image from the URL and save to your own path. You need to add
allow_url_fopen=On to your php.ini file for the below code to work */
file_put_contents($img, file_get_contents("https://your_image.com/pic.jpg"));
$post_fields = array('chat_id' => $chat_id,
'photo' => new CURLFile(realpath($img)),
'caption' => $caption
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type:multipart/form-data"
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
$output = curl_exec($ch);
curl_close($ch); //close curl
That's all!

PHP cURL POST returns a 415 - Unsupported Media Type

I've got a simple PHP script that sends an HTTP POST request via cURL, and expects a json string in response (would have loved to use an existing library like pecl_http/HTTPRequest for this, but can't). The call consistently fails with a 415 error - Unsupported Media Type. I think I'm not configuring cURL correctly, but after much searching, I can't find out what I'm doing wrong. Here's some code:
class URLRequest
{
public $url;
public $headers;
public $params;
public $body;
public $expectedFormat;
public $method;
public function URLRequest($aUrl, array $aHeaders, array $aParams, $aFormat = "json", $isPost = false, $aBody = "+")
{
$this->url = $aUrl;
$this->headers = $aHeaders;
$this->params = $aParams;
$this->expectedFormat = $aFormat;
$this->method = ($isPost ? "POST" : "GET");
$this->body = $aBody;
}
public function exec()
{
$queryStr = "?";
foreach($this->params as $key=>$val)
$queryStr .= $key . "=" . $val . "&";
//trim the last '&'
$queryStr = rtrim($queryStr, "&");
$url = $this->url . $queryStr;
$request = curl_init();
curl_setopt($request, CURLOPT_URL, $url);
curl_setopt($request, CURLOPT_HEADER, 1);
curl_setopt($request, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
if($this->method == "POST")
{
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
//this prevents an additions code 100 from getting returned
//found it in some forum - seems kind of hacky
curl_setopt($request, CURLOPT_HTTPHEADER, array("Expect:"));
}
$response = curl_exec($request);
curl_close($request);
preg_match("%(?<=HTTP/[0-9]\.[0-9] )[0-9]+%", $response, $code);
$resp = "";
if($this->expectedFormat == "json")
{
//parse response
}
elseif($this->expectedFormat == "xml")
{
//parse response
}
return $resp;
}
}
$url = "http://mydomain.com/myrestcall";
$query = array( "arg_1" => "test001",
"arg_2" => "test002",
"arg_3" => "test003");
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"Accept" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
$body = array( "body_arg_1" => "test021",
"body_arg_2" => array("test022", "test023"),
"body_arg_3" => "test024");
$request = new URLRequest($url, $headers, $query, "json", true, $body);
$response = $request->exec();
...and the response:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Type: text/html;charset=utf-8
Content-Length: 1047
Date: Mon, 18 Jun 2012 16:30:44 GMT
<html><head><title>JBoss Web/2.1.3.GA - Error report</title></head><body><h1>HTTP Status 415 - </h1><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().</u></p><h3>JBoss Web/2.1.3.GA</h3></body></html>
Any insights or ideas?
Thanks in advance!
Problem solved! Here's the issue:
Sending an associative-array of headers DOES NOT WORK with cURL. There are several forums scattered around that show examples using an associative array for headers. DON'T DO IT!
The correct way (which is also scattered around the internets, but that I'm too dense to have noticed) is to construct your header key/value pairs as strings, and pass a standard array of these strings when setting the CURLOPT_HTTPHEADER option.
So in summary,
WRONG:
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
RIGHT:
$headers = array( "Accept-Encoding: gzip",
"Content-Type: application/json",
"custom_header_1: test011",
"custom_header_2: test012",
"custom_header_3: test013");
I hope this comes in handy to some other noble doofus down the road before they waste as much time debugging as I did.
If I had to guess, I would assume that the same rule applies to the POST body key/value pairs as well, which is why #drew010 's comment about using http_build_query() or json_encode() to stringify your message body is a great idea as well.
Thanks to everyone for your very useful comments, and for you time and consideration. In the end, a side by side comparison of the http traffic (captured via Wireshark) revealed the issue.
Thanks!
I think the problem is that you are passing an array as the CURLOPT_POSTFIELDS option. By passing an array, this forces the POST request to use multipart/form-data when the server is probably expecting application/x-www-form-urlencoded.
Try changing
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
to
curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query($this->body));
See http_build_query for more information and also this answer: My cURL request confuses some servers?
I had the same problem and I fixed changing the header.
My code:
$authorization = 'authorization: Bearer '.trim($apiKey);
$header = [
'Content-Type: application/json',
$authorization
];
curl_setopt($session, CURLOPT_HTTPHEADER, $header);
I don't know why the array function doesn't work :
curl_setopt($session, CURLOPT_HTTPHEADER, array('Content-Type:
application/json',
$authorization));
This worked for me
$data ="data";
$headers = [
"Content-Type: application/json",
"X-Content-Type-Options:nosniff",
"Accept:application/json",
"Cache-Control:no-cache"
];
$auth = $USER . ":" . $PASSWORD;
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_ENCODING, "");
curl_setopt($curl,CURLOPT_MAXREDIRS, 10);
curl_setopt($curl,CURLOPT_TIMEOUT, 0);
curl_setopt($curl,CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_USERPWD, $auth);
curl_setopt($curl,CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($curl);

Multipart PUT upload using Curl and PHP to a REST endpoint

I need to HTTP PUT a csv file and some POST fields using multipart POST with PHP and Curl to a REST API endpoint.
The contents of the file upload is stored in a variable $list. The other end point is $url.
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PUT, true);
$post = array(
//Other Post fields array
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$fh = fopen('php://memory', 'rw');
fwrite($fh, $list);
rewind($fh);
curl_setopt($ch, CURLOPT_INFILE, $fh);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($list));
$response = curl_exec($ch);
The above code seems to work the only problem is that the other end point requires a specific fieldname for the file upload. How do i set a filename ?
Am i doing something wrong ?
This is the PUT format they have mentioned on API
Content-Disposition: form-data; name="list[csv]"; filename="RackMultipart20110923-63966-hfpyg"
Content-Length: 33
Content-Type: text/csv
Content-Transfer-Encoding: binary
xxxx
yyyy
zzzz
-------------MultipartPost
Content-Disposition: form-data; name="list[list_type]"
Blacklist
-------------MultipartPost--
FYI that is multipart/form-data. You will need to build the body yourself I think, I don't think cURL could be made to build that sort of request with a PUT request. However, this is not a serious problem:
<?php
function recursive_array_mpfd ($array, $separator, &$output, $prefix = '') {
// Recurses through a multidimensional array and populates $output with a
// multipart/form-data string representing the data
foreach ($array as $key => $val) {
$name = ($prefix) ? $prefix."[".$key."]" : $key;
if (is_array($val)) {
recursive_array_mpfd($val, $separator, $output, $name);
} else {
$output .= "--$separator\r\n"
. "Content-Disposition: form-data; name=\"$name\"\r\n"
. "\r\n"
. "$val\r\n";
}
}
}
// This will hold the request body string
$requestBody = '';
// We'll need a separator
$separator = '-----'.md5(microtime()).'-----';
// First add the postfields
$post = array(
//Other Post fields array
);
recursive_array_mpfd($post, $separator, $requestBody);
// Now add the file
$list = "this,is,some,csv,data"; // The content of the file
$filename = "data.csv"; // The name of the file
$requestBody .= "--$separator\r\n"
. "Content-Disposition: form-data; name=\"list[list_type]\"; filename=\"$filename\"\r\n"
. "Content-Length: ".strlen($list)."\r\n"
. "Content-Type: text/csv\r\n"
. "Content-Transfer-Encoding: binary\r\n"
. "\r\n"
. "$list\r\n";
// Terminate the body
$requestBody .= "--$separator--";
// Let's go cURLing...
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: multipart/form-data; boundary="'.$separator.'"'
));
$response = curl_exec($ch);
If you have any problems with this, try echo $requestBody; before the cURL request and make sure it looks like you expect it to.

CURL - php vs command line bash

From bash terminal, I successfully executed the following command.
curl -v -L -F file='#/var/www/dev/public_html/sixties.mov' -F title='my video' -F description='this is a video' -F language='eng' -F license='a2be14e1-37d9-11dd-ae16-0800200c9a66' -F country='US' http://johnuser:johnpass#website.com/api/media
Now I want to create a PHP script that uses the phpcurl library to execute an equivalent command. My code below is shown, but it's not working. The http://johnuser:johnpass#website.com/api/media server is giving me a generic error message. I'm pretty sure I'm making a mistake by not passing the right parameters or setting the right flags in my php code. Can anyone tell me what's wrong?
$url = 'http://johnuser:johnpass#website.com/api/media';
$fields = array();
$fields['file'] = '#/var/www/dev/public_html/sixties.mov';
$fields['title'] = 'my video';
$fields['description'] = 'this is a test';
$fields['language'] = 'eng';
$fields['country'] = 'US';
$fields['license'] = 'a2be14e1-37d9-11dd-ae16-0800200c9a66';
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
$ch = curl_init();
//set the url, number of POST vars, POST data
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, true);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
print_r($result);
The error message I got is {"status":{"message":"typeMismatch ","error":true,"code":500}}
I think this is what you need to be doing, if you want upload a file:
// Parameters
$url = 'http://website.com/api/media';
$username = 'johnuser';
$password = 'johnpass';
$upload_file = '/var/www/dev/public_html/sixties.mov';
// Declare a couple of arrays we will need
$fields = $headers = array();
// Standard POST fields
$fields['title'] = 'my video';
$fields['description'] = 'this is a test';
$fields['language'] = 'eng';
$fields['country'] = 'US';
$fields['license'] = 'a2be14e1-37d9-11dd-ae16-0800200c9a66';
// Boundary string for multipart message
$boundary = '--=-=-'.md5(uniqid()).rand().'-=-=--';
// Start the body with the file to be uploaded
$body = "--$boundary\r\n"
. "Content-Disposition: form-data; name=\"file\"; filename=\"".basename($upload_file)."\"\r\n"
. "Content-Type: application/octet-stream\r\n" // You should put the right MIME type here
. "\r\n"
. file_get_contents($upload_file) . "\r\n";
// Loop the fields and build the rest of the body
foreach ($fields as $name => $value) {
$body .= "--$boundary\r\n"
. "Content-Disposition: form-data; name=\"$name\"\r\n"
. "\r\n"
. "$value\r\n";
}
// Finish the body
$body .= "--$boundary--";
// Add a couple of headers
$headers[] = "Content-Type: multipart/form-data; boundary=\"$boundary\"";
$headers[] = 'Content-Length: ' . strlen($body);
$ch = curl_init();
// Set the cURL options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// Execute post
$result = curl_exec($ch);
// Close connection
curl_close($ch);
print_r($result);
POST file uploads are done with a MIME multipart message, using the multipart/form-data sub-type.

Post CSV to Google Docs Folder

Working on a PHP script to essentially dump the results of a query into a .csv and then upload to a specific folder on our enterprise Google Docs.
The file is created and sent over to Docs just fine. However, it isn't being placed in the proper directory.
This is the function I'm using where $file, $folder, and $newtoken are strings like 'dump.csv', '0B0rVKeOmIwGXMGU2MzYyN2EtZWV...', [auth token from Google].
function insert($file, $folder, $newtoken){
$mime = "Media multipart posting\n--END_OF_PART\n";
$mime .= "Content-Type: application/atom+xml\n\n";
$xml="<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:docs=\"http://schemas.google.com/docs/2007\">
<category scheme=\"http://schemas.google.com/g/2005#kind\"
term=\"http://schemas.google.com/docs/2007#document\"/>
<title>example document</title>
<docs:writersCanInvite value=\"true\" />
</entry>
";
$mime.=$xml."\n--END_OF_PART\n";
$document = "Content-Type: text/plain\n\n";
$handle = fopen($file, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$document.=$contents;
$itemURL = "https://docs.google.com/feeds/default/private/full";
$mime .= $document."\n--END_OF_PART--\n";
$headers = array();
$headers[] = "POST /feeds/default/private/full/folder%3A".$folder."/contents HTTP/1.1";
$headers[] = "Host: docs.google.com";
$headers[] = "GData-Version: 3.0";
$headers[] = "Authorization: GoogleLogin auth=".$newtoken."";
$headers[] = "Content-Length: ".strlen($mime);
$headers[] = "Content-Type: multipart/related; boundary=END_OF_PART";
$headers[] = "Slug: Test";
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$itemURL);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl,CURLOPT_POSTFIELDS, $mime);
$result = curl_exec($curl);
curl_close($curl);
echo 'Response: '.$result;
}
Maybe I have the folder ID wrong (just copied from URL while viewing in Google Docs)?
Bonus: Can I manipulate the content-type headers to get Google to convert the file to a spreadsheet?
You have
$headers[] = "POST /feeds/default/private/full/folder%3A".$folder."/contents HTTP/1.1";
and then:
curl_setopt($curl,CURLOPT_URL,$itemURL);
Make up your mind. I think the first one is wrong; you can't change the URL via the CURLOPT_HTTPHEADER option. Set $itemURL to the full URL (including /feeds/default/private/full/folder%3A".$folder."/contents) and remove the first line.

Categories