2013-12-15

force.com REST APIでコンテンツ作るのが面倒くさかったので共有

force.com SOAP APIでコンテンツ(ContentVersion)上げるのは普通にレコード作るだけで良くて

実データもBase64エンコードしたバイナリをVersionData項目に入れるだけですごく簡単。

 

force.com REST APIでも通常のCRUDと同じようにできるかと思ったが、

バイナリデータをアップロードするには結構面倒くさいみたいなので共有しまっす。

 

リファレンスを読むとmultipart/form-data形式で送らないとダメっぽい。

以下はphp(curl使用)のサンプル

define("SFDC_CLIENT_KEY", "Input Your Client Key");
define("SFDC_CLIENT_SECRET", "Input Your Client Secret");
define("SFDC_USERNAME", "Input Your SFDC User Name");
define("SFDC_PASSWORD", "Input Your SFDC Password");
define("SFDC_TOKEN_URL", "https://login.salesforce.com/services/oauth2/token");
define("SFDC_REST_VERSION", "27.0");
define("SFDC_CONTENTS_LIBRARY_ID", "");

$sf = new SforceRest(SFDC_CLIENT_KEY, SFDC_CLIENT_SECRET, SFDC_USERNAME, SFDC_PASSWORD);

$json = "--boundary_string" . PHP_EOL;
$json .= "Content-Disposition: form-data; name=\"Nandemo OK\";" . PHP_EOL;
$json .= "Content-Type: application/json" . PHP_EOL . PHP_EOL;
$json .= json_encode(array(
    'Title' => "Input Your ContentVersion Title" ,
    'PathOnClient' => "Input Your Upload FileName",
    'Description' => 'Input Your ContentVersion Description',
//    'FirstPublishLocationId' => SFDC_CONTENTS_LIBRARY_ID  
)) . PHP_EOL .PHP_EOL;
$json .= "--boundary_string" . PHP_EOL;
$json .= "Content-Type: application/json" . PHP_EOL;
$json .= "Content-Disposition: form-data; name=\"VersionData\";filename=\"test.pdf\"" . PHP_EOL . PHP_EOL;
$json .= file_get_contents("test.pdf") . PHP_EOL . PHP_EOL;
$json .= "--boundary_string--";

$sf->insertContentVersion($json);

class SforceRest {
    private $loginInfo;

    /**
     * コンストラクタ(ログイン)
     * @param type $client_key
     * @param type $client_secret
     * @param type $user
     * @param type $password
     */
    function __construct ($client_key, $client_secret, $user, $password) {
        $ch = curl_init(SFDC_TOKEN_URL);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        $post_data = array(
            "grant_type" => "password",
            "client_id" => $client_key,
            "client_secret" => $client_secret,
            "username" => $user,
            "password" => $password
        );
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $res = curl_exec($ch);
        $this->loginInfo = json_decode($res);
    }

    /**
     * コンテンツにデータを格納
     * @param $json コンテンツのデータ
     */
    public function insertContentVersion($json) {
        $ch = curl_init("{$this->loginInfo->instance_url}/services/data/v" . SFDC_REST_VERSION . "/sobjects/ContentVersion");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Authorization: Bearer {$this->loginInfo->access_token}",
            "Content-Type: multipart/form-data;boundary=\"boundary_string\""
        ));

        curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        $res = curl_exec($ch);
        return json_decode($res);
    }
}

 

phpのcurlライブラリ使ってんだから

本文ベタ打ちせずに、もうちょっと簡単に作れないかと思ったけどダメな感じでした。

 

multipart/form-dataで送るにはcurlのPOSTデータを配列にすれば良いんだが

ファイル以外のContent-Typeを指定できないっぽくて

force.com REST API ではblob形式のファイルアップロードは項目部分を

application/jsonとかapplication/xmlに指定しないとNGレスポンスが返って来る仕様なので

curlライブラリではどうやらダメっぽいです。

 

ここのContent-Type指定できさえすれば、もうちょい直感的でわかりやすいんだけどなー。

 

ということで、サンプルみたいに素直にHeader指定して本文作って送っちゃった方が良さげっす。

たいしたコード量じゃないし…。

 

force.com REST APIでのコンテンツアップロードに関する詳細はこちらから↓

http://www.salesforce.com/us/developer/docs/api_rest/index_Left.htm#CSHID=dome_sobject_insert_update_blob.htm%23inserting_a_contentversion|StartTopic=Content%2Fdome_sobject_insert_update_blob.htm%23inserting_a_contentversion|SkinName=webhelp

 

コンテンツの項目の詳細は以下のリンクから↓

http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_contentversion.htm

 

 

このエントリーをはてなブックマークに追加