Does RESTFul server running with services module really support multipart/form-data request parsin?
Question
I have been trying for a long to get a file upload to work from my lisp application using an HTTPPost. I am running the services module on Drupal 7 with the a RESTFul server (with the file resource enabled). I am able to connect to the server and login then use the cookie that is returned to send another http-post to ?q=rest/file which includes the file. This post has a content type of multipart/form-data and always returns 200 OK but the file upload never occurs.
I tried doing a similar post from php CURL and it uploaded without a hitch. When I set CURLOPT_VERBOSE and examined the header of the successful POST, I noticed that the content-type was application/x-www-form-urlencoded
. Finally I decided to try and change the content-type in my curl example to a multipart/form-data looking like this: multipart/form-data; boundary=----------PrqXvhHr3Bb68fVcGv7ohf0K6OOSsi0R4M4JpYPlA4rovP56s7
and now the file is no longer properly uploaded (but still returns success).
I am now thinking maybe I am having all this trouble because the RESTful server does not work with multipart/form-data requests. Does anyone know? Has anyone tried this? All the documentation I have read suggests that file transfers should always be done with multipart/form-data.
Here is the code I am using to do the file upload through php/curl in case anyone might find it useful in understanding this problem:
<?php
// node data
$filename = '/Users/mike/hello.png';//'C:\Users\Mike\Desktop\hello.png';
$title = 'A node created with services 3.x and REST server';
$body = '<p>Body lorem ipsum</p>';
$tags = 'TEST_TAG, TEST_TAG2';
$type = 'test'; // node type
$vid = 2; // vid of vocabulary marked as "Tags"
$services_url = 'http://localhost:8888/?q=rest';
/*
* Server REST - user.login
*/
// REST Server URL for auth
$request_url = $services_url . '/user/login';
// User data
$user_data = array(
'username' => 'login',
'password' => 'password',
);
$user_data = http_build_query($user_data);
$fp = @fopen("/Users/Mike/curl-error.log", "w");//'/Users/Mike/curl-error.log';
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE); // Ask to not return Header
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Check if login was successful
if ($http_code == 200) {
// Convert json response as array
$logged_user = json_decode($response);
}
else {
// Get error msg
$http_message = curl_error($curl);
die('Auth error ' . $http_message);
}
// Define cookie session
$cookie_session = $logged_user->session_name . '=' . $logged_user->sessid;
/*
* Server REST - file.create
*/
if(!file_exists($filename)) {
die('File not exists');
}
if(!is_readable($filename)) {
die('File not readable');
}
// file
$file = array(
'filesize' => filesize($filename),
'filename' => basename($filename),
'file' => '@' . $filename, //'file' => base64_encode(file_get_contents($filename)),
'uid' => $logged_user->user->uid,
);
$file = http_build_query($file);
// REST Server URL for file upload
$request_url = $services_url . '/file';
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($curl, CURLOPT_STDERR, $fp);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $file); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE); // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
curl_setopt_array($curl, array(CURLINFO_HEADER_OUT => true) );
$response = curl_exec($curl);
//$postdata = file_get_contents("php://input");
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$headerSent = curl_getinfo($curl, CURLINFO_HEADER_OUT );
// Check if login was successful
if ($http_code == 200) {
// Convert json response as array
$file_data = json_decode($response);
}
else {
// Get error msg
$http_message = curl_error($curl);
die('Sending file error<br>' . $http_message . "\n<br>");
}
// file id (nessesary for node)
$fid = $file_data->fid;
/*
* Server REST - node.create
*/
// REST Server URL
$request_url = $services_url . '/node';
// Node data
$node_data = array(
'title' => $title,
'type' => $type,
'body' => $body,
'taxonomy[tags][' . $vid . ']' => $tags,
'field_main_image[]' => array('fid' => $fid, 'list' => 1, 'data' => NULL),
);
$node_data = http_build_query($node_data);
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $node_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE); // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Check if login was successful
if ($http_code == 200) {
// Convert json response as array
$node = json_decode($response);
}
else {
// Get error msg
$http_message = curl_error($curl);
die('Getting data error<br>' . $http_message . "\n<br>");
}
print_r($node);
No correct solution