プログラマ38の日記

主にプログラムメモです。

Salesforce: apache httpclient / commons http を使ってREST APIでファイル(ContentVersion)を登録する

Salesforceへバイナリファイルを連携するには、通常はデータローダをはじめとするSOAP APIを使いbase64変換した文字列を送信します。

 

ファイル(ContentVersion)は2GBと大きいサイズでも登録が可能ですが、SOAP APIでは、Base64変換後のサイズで50MBのサイズ制限があります。

Base64変換では1割以上サイズが増えるため物理サイズとしてはもっと小さくなります)

 

ですが、REST APIではその制限はなく50MBより大きなサイズでも登録できます。SOAP APIだとできなくて、REST APIだとできることの1つだと思います。

 

javaプログラムで、REST APIを使ったファイルを登録するサンプルを作りました。

また、サンプルでは、apache httpclient 4.5.3と、commons http 3.1を使ったプログラムを作成してみました。

 

apache httpclient 4.5.3を使ったサンプル

   (さらに、SOAP API用にwsc、Json用にGsonを利用しています。)

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.HttpClientBuilder;

import com.google.gson.Gson;
import com.sforce.soap.partner.Connector;
import com.sforce.soap.partner.LoginResult;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectorConfig;


public class MainHTTPClient4 {

  public static void main(String[] args) throws Exception{
    
    ConnectorConfig cc = new ConnectorConfig();
    cc.setManualLogin(true);
    PartnerConnection pc = Connector.newConnection(cc);
    
    LoginResult lr = pc.login("sampleuser@sample.user", "samplepassword");
    
    String url =lr.getServerUrl();
    String sessionId = lr.getSessionId();

    HttpPost post = new HttpPost(url.substring(0, url.indexOf("/services")) + "/services/data/v41.0/sobjects/ContentVersion");
    post.addHeader("Authorization", ":Bearer " + sessionId);
    
    File file = new File("登録したいファイル");
    
    HashMap<String, String> contentvalue = new HashMap<String, String>();
    contentvalue.put("Title","sampletitle");
    contentvalue.put("SharingOption","A");
    contentvalue.put("SharingPrivacy","N");
    contentvalue.put("PathOnClient",file.getName());
    contentvalue.put("ContentLocation","S");
    String jsonstr =new Gson().toJson(contentvalue);
    
    MultipartEntityBuilder entity = MultipartEntityBuilder.create();
    entity.addTextBody("entity_data", jsonstr,ContentType.APPLICATION_JSON);
    entity.addBinaryBody("VersionData", file);
    
    post.setEntity(entity.build());
    
    HttpClient client = HttpClientBuilder.create().build();
    HttpResponse response = client.execute(post);

    ByteArrayOutputStream byteout = new ByteArrayOutputStream();
    
    response.getEntity().writeTo(byteout);
    
    System.out.println( new String(byteout.toByteArray()) );

  }
}

 

commons http 3.1を使ったサンプル

(さらに、SOAP API用にwsc、Json用にGsonを利用しています。)

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

import com.google.gson.Gson;
import com.sforce.rest.ContentType;
import com.sforce.rest.RestConnection;
import com.sforce.soap.partner.Connector;
import com.sforce.soap.partner.LoginResult;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectorConfig;


public class MainCommonsHttp3 {

  public static void main(String[] args) throws Exception{
    ConnectorConfig cc = new ConnectorConfig();
    cc.setManualLogin(true);
    PartnerConnection pc = Connector.newConnection(cc);
    
    LoginResult lr = pc.login("sampleuser@sample.user", "samplepassword");
    
    String url =lr.getServerUrl();
    String sessionId = lr.getSessionId();
    
    HttpClient client = new HttpClient();
    
    PostMethod post = new PostMethod(url.substring(0, url.indexOf("/services")) + "/services/data/v41.0/sobjects/ContentVersion");
    post.setRequestHeader("Authorization", ":Bearer " + sessionId);

    File file = new File("登録したいファイル");
    
    HashMap<String, String> contentvalue = new HashMap<String, String>();
    contentvalue.put("Title","test1");
    contentvalue.put("SharingOption","A");
    contentvalue.put("SharingPrivacy","N");
    contentvalue.put("PathOnClient",file.getName());
    contentvalue.put("ContentLocation","S");
    String jsonstr =new Gson().toJson(contentvalue);
    
    StringPart contentrec = new StringPart("entity_data",jsonstr);
    contentrec.setContentType("application/json");
    FilePart fp = new FilePart("VersionData", file);
    fp.setContentType("application/excel");
    fp.setCharSet("binary");

    Part[] parts = new Part[] { contentrec,fp };
    post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));

    client.executeMethod(post);
    
    System.out.println( new String(post.getResponseBody()) );
  }
}

 

最後に

実はcommons http3.1だけでサンプルプログラムを作って試していたのですが、commons http3.1って相当古いよなーと思い、新しいライブラリで試したので2つのサンプルコードとなっています。

commons http3.1とapache httpclient 4.5.3では、バージョンアップとかそういう次元ではなく別物なんですね。。そもそも名前が変わっていますし。apache httpclient 4.5.3の方が心なしかすっきりしているような気がします。

 

また、REST APIなら大き目のファイルをアップロードできますと書いてはみたもの1GB とかのファイルでは試していません。(200MB程度のファイルは登録してみました。)

後、画面から登録するより多少遅い気がします。