The purpose of these enhancements are to permit uploading files when we create/update documents through the web service interface. This extension also adds functionality that permits establishing relationships with other entities to the document we are creating.
Calls to REST methods of Create, Retrieve and Update maintain their profile and keep working as before. This extension adds to these calls a set of special fields that will be acknowledged by the enhancements.
The special fields are:
relations | a comma separated list of webservice identifiers. |
filename | array with these fields: name: string, name of the file to upload, size: file size type: file type content: base64_encode(file) |
With the virtual field relations we can establish relationships between the document and any other record. For example, we can upload a document and automatically relate it with a trouble ticket (HelpDesk).
Since a document can be related to many other records, the relations parameter is a comma-separated list of entities. The document being created will be related to all of them.
This new relations field will also be returned when executing a Retrieve. The format will be a comma-separated list of related entities.
To permit uploading documents we have added another virtual field called filename. It is an array with the four values we need to upload an attachment:
As of coreBOS 5.6 you will also receive another virtual field when retrieving a document record. This field is called _downloadurl and represents the absolute path of the file attachment in the application. This will permit easy linking from external applications and websites. This functionality is especially useful for e-commerce sites.
This virtual field is also added to the query language when it is possible.
Next, you can find some examples.
<?php
include_once('cbwsclib/WSClient.php');
require_once 'debugoutput.php';
$url = 'http://localhost/corebos/webservice.php';
$wsClient = new WSClient($url);
// Login
if (!$wsClient->doLogin('admin', 'pon la que corresponda')) {
die('Login error.');
}
//name of the module for which the entry has to be created.
$moduleName = 'Documents';
// get file to upload
$finfo = finfo_open(FILEINFO_MIME); // return mime type ala mimetype extension
//$filename = 'createdoc.php';
$filename = 'image001.png';
$mtype = finfo_file($finfo, $filename); // posiblemente haya que instalar librerias PECL adicionales a PHP
$model_filename=array(
'name'=>$filename,
'size'=>filesize($filename),
'type'=>$mtype,
'content'=>base64_encode(file_get_contents($filename))
);
//fill in the details of the contacts.userId is obtained from loginResult.
$contactData = array(
//'assigned_user_id'=>$userId,
'notes_title' => 'REST Test createdoc',
'filename'=>$model_filename,
'filetype'=>$model_filename['type'],
'filesize'=>$model_filename['size'],
'filelocationtype'=>'I',
'filedownloadcount'=> 0,
'filestatus'=>1,
'folderid' => '22x1',
'relations' => '9x66873', // besides creating the document it will relate it to this record
);
//encode the object in JSON format to communicate with the server.
$objectJson = Zend_JSON::encode($contactData);
if ($dcall==1) printvar("Create, sending in",$objectJson);
$response = $wsClient->doCreate($moduleName, $contactData);
if ($dcall==1) printvar("Raw response (json) Create",$response);
$id = $response['id'];
var_dump($response);
?>
There is no visual difference from a normal call, the difference is in the input parameters to the call and the changes that occur in the application.
<?php
include_once('cbwsclib/WSClient.php');
require_once 'debugoutput.php';
$url = 'http://localhost/corebos/webservice.php';
$wsClient = new WSClient($url);
// Login
if (!$wsClient->doLogin('admin', 'pon la que corresponda')) {
die('Login error.');
}
//name of the module for which the entry has to be created.
$moduleName = 'Documents';
// get file to upload
$finfo = finfo_open(FILEINFO_MIME); // return mime type ala mimetype extension
$filename = 'updatedoc.php';
$mtype = finfo_file($finfo, $filename); // posiblemente haya que instalar librerias PECL adicionales a PHP
$model_filename=array(
"name"=>$filename,
"size"=>filesize($filename),
"type"=>$mtype,
'content'=>base64_encode(file_get_contents($filename))
);
//fill in the details of the contacts.userId is obtained from loginResult.
$contactData = array(
'notes_title' => 'REST Test updatedoc',
'filename'=>$model_filename,
'filetype'=>$model_filename['type'],
'filesize'=>$model_filename['size'],
'filelocationtype'=>'I',
'filedownloadcount'=> 0,
'filestatus'=>1,
'folderid' => '22x1',
'id' => '7x134089',
// 'relations' NOT SUPPORTED ON UPDATE: use set_relations webservice call
);
//encode the object in JSON format to communicate with the server.
$objectJson = Zend_JSON::encode($contactData);
if ($dcall==1) printvar("Update, sending in",$objectJson);
$response = $wsClient->doUpdate($moduleName, $contactData);
if ($dcall==1) printvar("Raw response (json) Update",$response);
$id = $response['id'];
var_dump($response);
?>
There is no visual difference from a normal update call, the difference is in the input parameters to the call and the changes that occur in the application.
<?php
require 'dologin.php';
// To obtain the identifier of the document you can use the Query operation
$accountId = '7x134063';
//sessionId is obtained from loginResult.
$params = "sessionName=$sessionId&operation=retrieve&id=$accountId";
//Retrieve must be GET Request.
$httpc->get("$endpointUrl?$params");
$response = $httpc->currentResponse();
if ($dcall==1) printvar("Raw response (json) Retrieve",$response);
//decode the json encode response from the server.
$jsonResponse = Zend_JSON::decode($response['body']);
if ($dcall==1) printvar("Webservice response Retrieve",$jsonResponse);
//operation was successful get the token from the response.
if($jsonResponse['success']==false)
//handle the failure case.
die('retrieve failed:'.$jsonResponse['error']['message']);
$retrievedObject = $jsonResponse['result'];
var_dump($retrievedObject);
?>
Webservice response Retrieve
array
'success' => boolean true
'result' =>
array
'notes_title' => string 'testd1' (length=6)
'createdtime' => string '2013-10-15 12:08:06' (length=19)
'modifiedtime' => string '2013-10-15 12:08:06' (length=19)
'assigned_user_id' => string '19x1' (length=4)
'notecontent' => string '<p>fdfgdfgdsflm</p><p>fg</p><p>lfmg</p><p>alfkmg</p>' (length=52)
'filetype' => string 'text/x-sql' (length=10)
'filesize' => string '922' (length=3)
'filelocationtype' => string 'I' (length=1)
'fileversion' => string '' (length=0)
'filestatus' => string '1' (length=1)
'filedownloadcount' => string '3' (length=1)
'folderid' => string '22x1' (length=4)
'note_no' => string 'DOC5379' (length=7)
'id' => string '7x134063' (length=8)
'relations' => !!! THIS IS NEW !!!
array
0 => string '9x66873' (length=7) !!! related to record 66873 of the entity 9 !!!
'_downloadurl' => string 'http://localhost/coreBOSwork/storage/2014/August/week2/134063_1.jpg' (length=64)
This new REST method returns the base64 encoded file attached to the given document. This call is added with two goals in mind, to obtain information of the attachment of a document without downloading the whole file which would slow many operations, and to no have to add yet another virtual field to the native Retrieve operation to indicate if we want to receive the whole file or not.
The profile of the method is
retrievedocattachment(id:Id,returnfile:boolean):Map
id | a comma separated list of webservice identifiers. |
returnfile | 1 if we want the whole file, 0 if we just want the attachment information |
The response is an object with the fields of the attachment. For each given identifier we will get an array with this structure:
filename | is an array with the fields: name: string, name of the file to upload, size: file size type: file type content: base64_encode(file) |
If the parameter returnfile is 0, the field content will be empty (no file sent, reducing bandwidth usage and time)
Find next an example code of a call to this method followed by the resulting output.
<?php
require 'dologin.php';
//fill in the details of the document id. Can be obtained using vtwsbrowser
// select id from documents
$docId='7x134063';
//sessionId is obtained from loginResult.
$params = array("sessionName"=>$sessionId, "operation"=>'retrievedocattachment', "id"=>$docId,'returnfile'=>'1');
// must be POST Request.
$httpc->post("$endpointUrl", $params, true);
$response = $httpc->currentResponse();
if ($dcall==1) printvar("Raw response (json) RetrieveDocAttachment",$response);
//decode the json encode response from the server.
$jsonResponse = Zend_JSON::decode($response['body']);
if ($dcall==1) printvar("Webservice response RetrieveDocAttachment",$jsonResponse);
//operation was successful get the token from the reponse.
if($jsonResponse['success']==false)
//handle the failure case.
die('RetrieveDocAttachment failed: '.$jsonResponse['error']['message']);
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
//header('Content-Type: application/pdf'); FIXME
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header('Content-Disposition: attachment; filename="'.$jsonResponse['result']['0']['filename'].'"');
/*
The Content-transfer-encoding header should be binary, since the file will be read
directly from the disk and the raw bytes passed to the downloading computer.
The Content-length header is useful to set for downloads. The browser will be able to
show a progress meter as a file downloads. The content-lenght can be determined by
filesize function returns the size of a file.
*/
header("Content-Transfer-Encoding: binary");
echo base64_decode($jsonResponse['result']['0']['attachment']);
exit;
?>
Raw response (json) RetrieveDocAttachment
array
'url' => string 'http://localhost/corebos/webservice.php' (length=39)
'code' => int 200
'headers' =>
array
'date' => string 'Fri, 18 Oct 2013 08:41:30 GMT' (length=29)
'server' => string 'Apache/2.2.22 (Ubuntu)' (length=22)
'x-powered-by' => string 'PHP/5.3.10-1ubuntu3.8' (length=21)
'expires' => string 'Thu, 19 Nov 1981 08:52:00 GMT' (length=29)
'cache-control' => string 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' (length=62)
'pragma' => string 'no-cache' (length=8)
'content-length' => string '1376' (length=4)
'connection' => string 'close' (length=5)
'content-type' => string 'application/json' (length=16)
'body' => string '{"success":true,"result":{"7x134063":{"recordid":"134063","filetype":"text\/x-sql","filename":"restconfig.sql","filesize":922,"attachment":"LS0KLS0gUmV0cmVpdmUgRG9jdW1lbnQgYW5kIENoYW5nZSBEb2N1bWVudCBjbGFzcwotLQp1cGRhdGUgdnRpZ2VyX3dzX29wZXJhdGlvbl9zZXEgc2V0IGlkPWlkKzE7CklOU0VSVCBJTlRPIGB2dGlnZXJfd3Nfb3BlcmF0aW9uYCAoCmBvcGVyYXRpb25pZGAsCmBuYW1lYCAsCmBoYW5kbGVyX3BhdGhgICwKYGhhbmRsZXJfbWV0aG9kYCAsCmB0eXBlYCAsCmBwcmVsb2dpbmAKKQpWQUxVRVMgKAooc2VsZWN0IG1heChpZCkgZnJvbSB2dGlnZXJfd3Nfb3BlcmF0aW9uX3NlcSksJ3JldHJpZXZl'... (length=1376)
Webservice response RetrieveDocAttachment
array
'success' => boolean true
'result' =>
array
'7x134063' =>
array
'recordid' => string '134063' (length=6)
'filetype' => string 'text/x-sql' (length=10)
'filename' => string 'restconfig.sql' (length=14)
'filesize' => int 922
'attachment' => string 'LS0KLS0gUmV0cmVpdmUgRG9jdW1lbnQgYW5kIENoYW5nZSBEb2N1bWVudCBjbGFzcwotLQp1cGRhdGUgdnRpZ2VyX3dzX29wZXJhdGlvbl9zZXEgc2V0IGlkPWlkKzE7CklOU0VSVCBJTlRPIGB2dGlnZXJfd3Nfb3BlcmF0aW9uYCAoCmBvcGVyYXRpb25pZGAsCmBuYW1lYCAsCmBoYW5kbGVyX3BhdGhgICwKYGhhbmRsZXJfbWV0aG9kYCAsCmB0eXBlYCAsCmBwcmVsb2dpbmAKKQpWQUxVRVMgKAooc2VsZWN0IG1heChpZCkgZnJvbSB2dGlnZXJfd3Nfb3BlcmF0aW9uX3NlcSksJ3JldHJpZXZlZG9jYXR0YWNobWVudCcsICdpbmNsdWRlL1dlYnNlcnZpY2VzL1JldHJpZXZlRG9jQXR0YWNobWVudC5waHAnLCAndnR3c19yZXRyaWV2ZWRvY2F0dGFjaG1lbnQnLCAnUE9TVCcsICcw'... (length=1232)
Following a similar approach as the filename virtual field added for uploading document files, we have added also a generic virtual field to all the other modules in the application named attachments.
attachments is an array of file information for each image field contained in a module where you want to upload a file and can be used in Create, Update and Revise operations.
Let's suppose that you have two image fields on a module named cf_998 and cf_999. You can upload files to these two fields with an array like this:
$recordInfo = array(
...other fields in the record...
'cf_998' => 'barcode',
'cf_999' => 'somename',
'attachments' => array(
'cf_998' => array(
'name'=>'barcode', // no slash nor paths in the name
'size'=>strlen($file_data),
'type'=>'image/png',
'content'=>base64_encode($file_data)
),
'cf_999' => array(
'name'=>'somename', // no slash nor paths in the name
'size'=>strlen($file2_data),
'type'=>'application/pdf',
'content'=>base64_encode($file2_data)
),
),
...other fields in the record...
);
A normal Retrieve call on a record with images will return the information of the file; the name, the location on disk (URL), and some other metadata in a virtual field with the same name of the field followed by "imageinfo", but we have also added a method in order to retrieve file information of a record.
getRecordImages allows a web service client to retrieve the information of the image attachments associated with a record, which can then be used with the build/HelperScripts/getImageData.php script to obtain the image data itself.
Method: | getRecordImages |
Purpose: | Returns an array of file information for each image field of a module. |
Profile: | getRecordImages(id:string):Map |
Send as: | GET |
Parameters: | =>00id: web service id of the record with image fields we want to get. |
Response: | an array with: name, path, URL, type, internal ID, for each file in the record |
Examples:
The product module contains a special, non-standard image field which may contain many images. coreBOS does not recommend the use of this field. Individual images should be used instead.
When calling Retrieve on a product the first image found in the multi-image field will be returned. It is NOT guaranteed to always get the same image.
You can use the addProductImages method to insert images in this field.
Method: | addProductImages |
Purpose: | Inserts a set of images into the Product multi-image field |
Profile: | addProductImages(id:string, files:Map):Map |
Send as: | POST |
Parameters: | => id: web service ID of the product record to upload the images to => files: an array of images to upload, each array entry must contain two fields: name and content (base64 encoded) |
Response: | an array with information of the executed operations |
Next| Chapter 7: GenDoc and PDF output.