Tuesday, March 17, 2015

SharePoint Rest API to upload document

It was quite tricky to work with SharePoint API to upload document using Java, below is code to make it work. I had to use Apache HTTP client library for NTML authentication, rest of the work was to orchestrate different calls needed for SharePoint.

Here is the flow. You can also download the entire code from here.

1) Easy part, read the file with base64 bytes (unless you already have the bytes ready)

   private byte[] readFile(String fileName) throws Exception {  
     File file = new File(fileName);  
     FileInputStream fileInputStreamReader = new FileInputStream(file);  
     byte[] bytes = new byte[(int)file.length()];  
     byte[] encodedfile = Base64.encodeBase64(bytes);  
     return encodedfile;  

2) Initialize HTTP Client with NTLM authentication

     NTCredentials credentials = new NTCredentials(userName,password,localeMachineName,domain);  
     HttpClient httpClient = new HttpClient();  
     httpClient.getState().setCredentials(AuthScope.ANY, credentials);  

3) Get Form Digest value - you have to use context URL and post HTTP request in order to get Form Digest value. It is needed for the next call, otherwise SharePoint will return error message complaining about browser back button

   private String getFormDigestValue(String baseLocation, String contextInfoURI, HttpClient httpClient ) throws Exception {  
     String formDigestValue = "";  
     System.out.println("SharePointTestClient.getFormDigestValue URL: " + baseLocation + contextInfoURI );  
     PostMethod postMethod = new PostMethod(baseLocation + contextInfoURI);  
     int postResponseCode = httpClient.executeMethod(postMethod);  
     System.out.println("SharePointTestClient.getFormDigestValue postResponseCode " + postResponseCode );  
     for(org.apache.commons.httpclient.Header header : postMethod.getRequestHeaders() ) {  
       System.out.print("SharePointTestClient.getFormDigestValue postMethod request header " + header );  
     String responseBody = getResponseBody(postMethod);  
     System.out.println("SharePointTestClient.getFormDigestValue responseBody " + responseBody );  
     JSONObject jsonObject = (JSONObject) new JSONParser().parse(responseBody);  
     formDigestValue = (String)( (HashMap)((HashMap) jsonObject.get("d")).get("GetContextWebInformation") ).get("FormDigestValue");  
     System.out.println("SharePointTestClient.getFormDigestValue formDigestValue " + formDigestValue );  
     return formDigestValue;  

4) Last part is to send the HTTP Post to upload the document

     String postMethodLocation = baseLocation + "/_api/web/GetFolderByServerRelativeUrl('" + documentLibrary + "')/Files/add(url='" + uploadFileName + "',overwrite=true)";  
     System.out.println("SharePointTestClient.uploadFile postMethodLocation " + postMethodLocation );  
     PostMethod postMethod = new PostMethod(postMethodLocation);  
     postMethod.setRequestEntity(new ByteArrayRequestEntity(encodedfile));  
     postMethod.addRequestHeader("X-HTTP-Method", "POST");  
     int uploadFileResponseCode = httpClient.executeMethod(postMethod);  
     System.out.println(" Upload File Response Code " + uploadFileResponseCode );  
     String responseBody = getResponseBody(postMethod);  
     System.out.println("SharePointTestClient.uploadFile Upload File responseBody " + responseBody );  
     JSONObject jsonObject = (JSONObject) new JSONParser().parse(responseBody);  
     String uri = (String)( (HashMap)((HashMap) jsonObject.get("d")).get("__metadata") ).get("uri");  
     System.out.println("SharePointTestClient.uploadFile uri " + uri );  

Testing with parameters:

 sharePointTestClient.uploadFile("test.pdf", "test.pdf", "http://ecmdv.springsoa.com", "/_api/contextinfo", "Shared%20Documents", "chshah", "***********", "localhost", "adprod.springsoa.com" );  
 String fileName -  fileName to be read  
 String uploadFileName -  fileName (which will show up in SP)  
 String baseLocation -  base location, e.g. http://ecmdv.springsoa.com/contracts/na_03 or http://ecmdv.springsoa.com  
 String contextInfoURI -  context url to get form digest (e.g. /_api/contextinfo)  
 String documentLibrary -  document library or folder name (e.g. Docs )  
 String userName                 
 String password  
 String localeMachineName -  Not needed but client machine name  
 String domain -  domain name of the user