ApexからコールアウトでPOST送信する
apexクラスからコールアウトを使って外部APIにPOST送信してみた。
ファイルも一緒に送信する。
※追記
実際にこの内容で送信してみると、壊れたファイルが送信されてしまいます。
原因を調査中です。
※追記 2/27
動作したバージョンをアップしました。
基本的なPOST送信の方法
コールアウトで外部にHTTP送信する場合、
ヘッダーやボディの中身を順番に設定していき、送信、となる。
(この基本的な内容がわかっていなくて苦労した)
POSTやGETで送信されるデータの基本的な内容は以下。
[Web] HTTPリクエストの中身を学んでみた。GETやPOSTの違いなど
送信内容例はこんな感じ。(上記サイト内から引用)
POST /www.hoge.com/test.php HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: text/plain
Content-Length: 23
key1=value1&key2=value2
apexからの基本的なPOST送信の方法は以下。
[Salesforce][Force.com]外部サイトにHTTPアクセス(Callout)する
(上記サイトから引用、編集)
HttpRequest request = new HttpRequest();
request.setEndpoint('http://****アクセスしたいAPIのURLだよ!****');
request.setMethod('POSTとかGETとか!');
request.setHeader('Accept','text/plain, */*');
request.setHeader('Accept-Charset','Shift_JIS,utf-8;q=0.7,*;q=0.3');
request.setHeader('Accept-Encoding','gzip,deflate,sdch');
request.setHeader('Accept-Language','ja,en-US;q=0.8,en;q=0.6');
request.setHeader('Connection','keep-alive');
request.setHeader('Content-Type','text/xml; charset=UTF-8 ');
String prams = 'key1=value1&key2=value2';
request.setBody(prams);
Http http = new Http();
HttpResponse response = http.send(request);
String responseBody = response..getBody();
最初に上げた送信内容のボディ部分に、getパラメータのようにつなげて書かれている。
なので、そのようにボディ部分に書いてやればいい。
[Apex]WebコールアウトでPOST送信する場合のパラメータの設定方法は?
注意点としては、コールアウトするURLは事前にドメインを指定しておく必要があるよう。
指定してないと、Unauthorized endpoint, please check Setup->Security->Remote site settings.
とエラーが出る。
設定 -> セキュリティのコントロール -> リモートサイトの設定
さらに、接続するURLはSSLでないとエラーが返されてしまう。
The requested URL could not be retrieved
ちなみに、配列で送信する場合は以下。
params = 'hoge[]=huga&hoge[]=fuge';
request.setBody(params);
POSTでファイルを送信する
参考:Post ‘multipart/form-data’ out of Salesforce.com with APEX
スペイン語なので読めないけど、コード部分は読める。
そのまま送信すると、送信先のPHP側で、$_FILES
にデータが入っていた。
この方法で、ファイルと一緒にパラメータも送信するには、
POST送信する際のボディ内容を再現すればいいよう。
いまさら聞けないHTTPマルチパートフォームデータ送信
(上記内容から引用)
POST test.php HTTP/1.1\r\n
Host: satoxpochi.com\r\n
Content-Type: multipart/form-data; boundary=---------------------------102852708831426\r\n
Content-Length: 「ボディ部のサイズ」\r\n
\r\n
-----------------------------102852708831426\r\n
Content-Disposition: form-data; name="password"\r\n
\r\n
ponpoko\r\n
-----------------------------102852708831426\r\n
Content-Disposition: form-data; name="level"\r\n
\r\n
high\r\n
-----------------------------102852708831426\r\n
Content-Disposition: form-data; name="filename"; filename="text.txt"\r\n
Content-Type: application/octet-stream\r\n
Content-Transfer-Encoding: binary\r\n
\r\n
abcd
-----------------------------102852708831426--\r\n
このように、送りたい情報分だけ区切り線でつないでいけばいい。
(1つのパラメータで区切り1つ分!)
また、visualforceのinputでfileを送信するには以下のようにする。
[apexクラス]
public String FileName { get; set; }
public Blob FileBody { get; set; }
[visualforceページ]
<apex:inputFile value="{!FileBody}" filename="{!FileName}"/>
これで、FileName
にファイル名、FileBody
にファイルが入る。
これらを踏まえて、最終的な送信部分のソースは以下。
POSTでデータとファイルをコールアウトで送信する。
[Visualforceページ]
メールアドレス1:<apex:input value="{!Email1}" /><br />
メールアドレス2:<apex:input value="{!Email2}" /><br />
<br />
添付ファイル : <apex:inputFile value="{!FileBody}" filename="{!FileName}"/>
[apexクラス]
HttpRequest request = new HttpRequest();
request.setEndpoint('https://送信先アドレス.php');
request.setMethod('POST');
request.setHeader('Accept-Language', 'ja');
String boundary = String.valueOf(DateTime.now().getTime());
String body = '';
body+='------------' + boundary + '\r\n';
body+='Content-Disposition: form-data; name="to[]"\r\n';
body+='\r\n';
body+=Email1 + '\r\n';
body+='------------' + boundary + '\r\n';
body+='Content-Disposition: form-data; name="to[]"\r\n';
body+='\r\n';
body+=Email2 + '\r\n';
body+='------------' + boundary + '\r\n';
body+='Content-Disposition: form-data; name="data"; filename="' + FileName + '"\r\n';
body+='Content-Transfer-Encoding: base64\r\n';
String contentType = 'application/octet-stream';
body+='Content-Type: ' + contentType + '\r\n\r\n';
body+=EncodingUtil.base64Encode(FileBody);
body+='\r\n------------' + boundary + '--';
request.setHeader('Content-Type', 'multipart/form-data; boundary=----------' + boundary);
request.setHeader('Content-Length',String.valueof(body.length()));
request.setBody(body);
Http http = new Http();
HttpResponse response = http.send(request);
ResResult = response.getBody();
送信先のPHPでの受信内容は以下。
($_POST)
array(1) {
["to"]=> array(2) {
[0]=> string(14) "mail1@hoge.com"
[1]=> string(14) "mail2@huga.com"
}
}
($_FILES)
array(1) {
["data"]=> array(5) {
["name"]=> string(8) "test.txt"
["type"]=> string(24) "application/octet-stream"
["tmp_name"]=> string(14) "/tmp/phpcEwVr6"
["error"]=> int(0)
["size"]=> int(309276)
}
}