Hello friends, today are going to discuss DropBox Integration with Apex Salesforce. We all heard about the DropBox or store and share files. Those are the things Dropbox provided. Also, We can connect DropBox to Salesforce via Apex Rest API. So we easily upload and fetch files in salesforce.
With Dropbox for Salesforce, you always have access to the latest content. There are already App Exchange App which is a free Link. You can install this and work with files/folders.
Also, check this: What Is Named Credentials, AuthProvider & Use In Apex Salesforce
Highlights Point:
- Use Http callout in Apex Class
- For Authenication we use Outh 2.0 and get access token.
- Use Refresh token for get access token.
- Use Json Parser for parse the json data get in response.
- Show error on any error in callout
Step:1 First we create an Account in DropBox click here, this is the developer link.
click App console and create an account
Step 2: Create a connected app so we can do further processes. click this to create an app.
Step 3: In this step, we will set up app. check below image.
Key Required Fields:
- redirect Url, here you can vf page url
- set scope read write files and folder
- you can setup you team here.
Code Samples :
Step 1: In this step, we will create an Apex Class for Post and Get HTTP Callout to DropBox.
Create methods like create a folder, delete a folder, upload files & get Access Token in class.
DropBoxCtrl.cls:
public with sharing class DropBoxCtrl {
private String apiKey;
private String apiSecret;
private String redirectURI;
private String Dropbox_Account_endpoint;
private String Dropbox_files_endpoint;
private String Dropbox_OAuth_authorize;
private String Dropbox_OAuth_token;
private String authorizationCode;
private String refreshToken;
public String code { get; set; }
public String username { get; set; }
public String fileName { get; set; }
public Blob fileBody { get; set; }
public Boolean success { get; set; }
public Boolean connected { get; set; }
public Boolean isError{get;set;}
public String errorMessage{get;set;}
public String successMessage{get;set;}
public Boolean isSuccess{get;set;}
public DropBoxCtrl() {
connected = false;
success = false;
successMessage = '';
apiKey = 'bw2o9zq6ztxxxxx'; // this is your dropbox apikey
apiSecret = 'xxxxxxxxx'; // this is your dropbox api secret
redirectURI = 'https://rijudelta-dev-ed--c.ap4.visual.force.com/apex/dropbox'; // url of the vf page in which the dropbox login is done
Dropbox_Account_endpoint = 'https://api.dropboxapi.com/2/users/get_current_account';
Dropbox_files_endpoint = 'https://content.dropboxapi.com/1/files_put/auto/';
Dropbox_OAuth_authorize = 'https://www.dropbox.com/oauth2/authorize';
Dropbox_OAuth_token = 'https://api.dropboxapi.com/oauth2/token';
code = ApexPages.currentPage().getParameters().get('code');
if(code != null) {
connected = true;
authorizationCode = code;
getAccessToken();
fetchUserInfo();
}
}
public PageReference getAuthorizationCode() {
String uri = Dropbox_OAuth_authorize +
'?client_id=' + apiKey +
'&response_type=code' +
'&redirect_uri=' + redirectURI;
PageReference pr = new PageReference(uri);
pr.setRedirect(true);
return pr;
}
private void getAccessToken() {
if(authorizationCode != null) {
try {
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(Dropbox_OAuth_token);
string bodyRequest = '';
bodyRequest = 'code=' + EncodingUtil.urlEncode(authorizationCode, 'UTF-8');
bodyRequest+= '&client_id=' + EncodingUtil.urlEncode(apiKey, 'UTF-8');
bodyRequest+= '&client_secret=' + EncodingUtil.urlEncode(apiSecret, 'UTF-8');
bodyRequest+= '&redirect_uri=' + EncodingUtil.urlEncode(redirectURI, 'UTF-8');
bodyRequest+= '&grant_type=authorization_code';
req.setBody(bodyRequest);
req.setHeader('Content-length', string.ValueOf(bodyRequest.length()));
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setMethod('POST');
req.setTimeout(60*1000);
HttpResponse res = h.send(req);
system.debug(res.getBody());
map<string, string> jsonValues = new map<string, string>();
jsonValues = parseJSONToMap(res.getBody());
if(jsonValues.containsKey('error')) {
isError = true;
errorMessage = 'Could not connect to DropBox!!';
connected = false;
}
else {
connected = true;
isSuccess = true;
refreshToken = jsonValues.get('access_token');
}
}
catch(Exception e) {
isError = true;
errorMessage = 'Could not connect to DropBox!!';
}
}
else{
isError = true;
errorMessage = 'Could not connect to DropBox!!';
}
}
// method that returns the user data of the connected dropbox account
private void fetchUserInfo() {
if(refreshToken != null) {
try {
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(Dropbox_Account_endpoint);
req.setHeader('Authorization', 'Bearer '+refreshToken);
req.setMethod('POST');
req.setTimeout(60*1000);
HttpResponse res = h.send(req);
system.debug(res.getBody());
Map<string, string> jsonValues = new Map<string, string>();
jsonValues = parseJSONToMap(res.getBody());
if(jsonValues.containsKey('error')){
isError = true;
errorMessage = 'Could not connect to DropBox!!';
}
else {
username = jsonValues.get('email');
isSuccess = true;
successMessage = 'DropBox Account : '+ username + ' Connect Successfully';
}
}
catch(Exception e) {
isError = true;
errorMessage = 'Could not connect to DropBox!!';
}
}
}
public void createFolder(){
isError = false;
String endPoint = 'https://api.dropboxapi.com/2/files/create_folder_v2';
String body = '{"path": "/Test","autorename": false}';
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
req.setEndpoint(endpoint);
req.setHeader('Authorization', 'Bearer '+refreshToken);
req.setHeader('Content-Type', 'application/json');
req.setMethod('POST');
req.setBody(body);
res = http.send(req);
Map<string, string> jsonDataMap = new Map<string, string>();
jsonDataMap = parseJSONToMap(res.getBody());
if(jsonDataMap.containsKey('error')){
isError = true;
errorMessage = 'Create Folder Process failed!!';
}
else {
successMessage = 'Folder Created Successfully!!';
isSuccess = true;
}
}
public void deleteFolderOrFile(){
String endPoint = 'https://api.dropboxapi.com/2/files/delete_v2';
String body = '{"path": "/Test"}';
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setHeader('Authorization', 'Bearer '+refreshToken);
req.setHeader('Content-Type', 'application/json');
req.setMethod('POST');
req.setBody(body);
HttpResponse res = http.send(req);
system.debug(res);
Map<string, string> jsonDataMap = new Map<string, string>();
jsonDataMap = parseJSONToMap(res.getBody());
if(jsonDataMap.containsKey('error')){
isError = true;
errorMessage = 'Delete Folder Process failed!!';
}
else {
successMessage = 'Folder Deleted Successfully!!';
isSuccess = true;
}
}
// method that uploads files to dropbox
public void uploadToDropBox(Blob file, String filename) {
try {
String boundary = '----------9889464542212';
String bodyEncoded = EncodingUtil.base64Encode(file);
Blob bodyEncoded2 = EncodingUtil.base64Decode(bodyEncoded);
String body = '{ "path": "/Homework/math/1.jpg", "mode": "add", "autorename": true, "mute": false, "strict_conflict": false }';
Http http = new Http();
HttpRequest req = new HttpRequest();
String endpoint = 'https://content.dropboxapi.com/2/files/upload';
//req.setEndpoint('callout:SalesforceBox/2/files/upload');
req.setEndpoint(endpoint);
req.setHeader('Authorization', 'Bearer '+refreshToken);
req.setHeader('Dropbox-API-Arg', body);
req.setHeader('Content-Type', 'application/octet-stream');
req.setHeader('Content-length', String.valueOf(bodyEncoded.length()));
req.setBody(body);
req.setBodyAsBlob(bodyEncoded2);
req.setMethod('POST');
req.setTimeout(60*1000);
HttpResponse resp = http.send(req);
system.debug(resp.getBody());
map<string, string> jsonDataMap = new map<string, string>();
jsonDataMap = parseJSONToMap(resp.getBody());
if(jsonDataMap.containsKey('error')){
isError = true;
errorMessage = 'Error:'+jsonDataMap.get('error');
} else{
successMessage = 'File Upload Successfully!!';
isSuccess = true;
}
}
catch(Exception e) {
isError = true;
errorMessage = 'Files couldn\'t be uploaded to Dropbox.';
}
}
private map<string, string> parseJSONToMap(string JSONValue){
JSONParser parser = JSON.createParser(JSONValue);
map<string, string> jsonMap = new map<string, string>();
string keyValue = '';
string tempValue = '';
while (parser.nextToken() != null) {
if(parser.getCurrentToken() == JSONToken.FIELD_NAME){
keyValue = parser.getText();
parser.nextToken();
tempValue = parser.getText();
jsonMap.put(keyValue, tempValue);
}
}
return jsonMap;
}
public void uploadFiles() {
uploadToDropBox(fileBody, fileName);
}
}
Step 2: In this step, we will create a Visualforce page. On this page, we will first authorize so URL redirect to dropbox auth and after auth, it will automatically come back to the Visualforce page with code parameter in URL.
After this, we Post this code with some required parameters because it access token get by grant_type=authorization_code.
DropBoxVf.vfp:
<apex:page showHeader="true" standardStylesheets="false" sidebar="true" applyBodyTag="false" docType="html-5.0" controller="DropBoxCtrl">
<html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>DropBox Salesforce Integration</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Import the Design System style sheet -->
<apex:slds />
</head>
<body>
<!-- REQUIRED SLDS WRAPPER -->
<div class="slds-scope">
<!-- PRIMARY CONTENT WRAPPER -->
<!-- RESPONSIVE GRID EXAMPLE -->
<div class="myapp">
<!-- header part -->
<div class="slds-tabs_card">
<div class="slds-page-header">
<div class="slds-page-header__row">
<div class="slds-page-header__col-title">
<div class="slds-media">
<div class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-opportunity" >
<svg aria-hidden="true" class="slds-icon ">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#opportunity">
</use>
</svg>
<span class="slds-assistive-text">Techdicer</span>
</span>
</div>
<div class="slds-media__body">
<div class="slds-page-header__name">
<div class="slds-page-header__name-title">
<h1>
<span>DropBox API Call From Apex</span>
<span class="slds-page-header__title slds-truncate" title="Recently Viewed">TechDicer</span>
</h1>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br/>
<!-- /header part -->
<apex:form id="myForm">
<!-- SPINNER -->
<div id="spinner" class="slds-spinner_container slds-is-absolute slds-hide" >
<div role="status" class="slds-spinner slds-spinner--large slds-spinner--brand">
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
<!-- / SPINNER -->
<div class="slds-grid slds-wrap">
<div class="slds-col slds-size--1-of-1 slds-small-size--1-of-1 slds-medium-size--1-of-1" style="text-align: center;">
<!-- card -->
<article class="slds-card">
<div class="slds-card__header slds-grid">
<header class="slds-media slds-media_center slds-has-flexi-truncate">
<div class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-account" title="account">
<svg class="slds-icon slds-icon_small" aria-hidden="true">
<use xlink:href="/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#account"></use>
</svg>
<span class="slds-assistive-text">account</span>
</span>
</div>
<div class="slds-media__body">
<h2 class="slds-card__header-title">
<a href="#" class="slds-card__header-link slds-truncate" title="Accounts">
<span>Accounts</span>
</a>
</h2>
</div>
<div class="slds-no-flex">
<apex:commandButton id="login" action="{!getAuthorizationCode}" value="Dropbox login" rendered="{!!connected}" styleClass="slds-button slds-button_brand"/>
<apex:commandButton action="{!createFolder}" value="Create Folder" styleClass="slds-button slds-button_brand slds-m-right_small" rendered="{!connected}"/>
<apex:commandButton action="{!deleteFolderOrFile}" value="Delete Folder/Files" styleClass="slds-button slds-button_brand" rendered="{!connected}"/>
</div>
</header>
</div>
<div class="slds-card__body slds-card__body_inner">
<!-- Error Toast -->
<apex:outputPanel rendered="{!isError}">
<div class="slds-notify_container slds-is-relative">
<div class="slds-notify slds-notify_toast slds-theme_error" role="status">
<span class="slds-assistive-text">error</span>
<span class="slds-icon_container slds-icon-utility-error slds-m-right_small slds-no-flex slds-align-top" title="Description of icon when needed">
<svg class="slds-icon slds-icon_small" aria-hidden="true">
<use xlink:href="/apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg#error"></use>
</svg>
</span>
<div class="slds-notify__content">
<h2 class="slds-text-heading_small">
<apex:outputText value="{!errorMessage}"></apex:outputText>
</h2>
</div>
</div>
</div>
</apex:outputPanel>
<!--/Error Toast -->
<!-- user success login -->
<apex:outputPanel rendered="{!isSuccess}">
<div class="slds-notify_container slds-is-relative">
<div class="slds-notify slds-notify_toast slds-theme_success" role="status">
<span class="slds-assistive-text">success</span>
<span class="slds-icon_container slds-icon-utility-success slds-m-right_small slds-no-flex slds-align-top" title="Description of icon when needed">
<svg class="slds-icon slds-icon_small" aria-hidden="true">
<use xlink:href="/apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg#success"></use>
</svg>
</span>
<div class="slds-notify__content">
<h2 class="slds-text-heading_small ">
{!successMessage}
</h2>
</div>
</div>
</div>
<br/><br/>
<!-- create/delete folder and upload files -->
<div class="slds-grid slds-wrap">
<div class="slds-col slds-size--1-of-1 slds-small-size--1-of-1 slds-medium-size--1-of-1">
<apex:inputFile id="file" value="{!fileBody}" filename="{!fileName}"></apex:inputFile>
<apex:commandButton action="{!uploadFiles}" value="Upload" styleClass="slds-button slds-button_brand"/>
</div>
</div>
<!-- /createdelete folder and upload files -->
</apex:outputPanel>
<!-- /user success login -->
</div>
<footer class="slds-card__footer">
</footer>
</article>
<!--/card -->
</div>
</div>
</apex:form>
</div>
<!-- / RESPONSIVE GRID EXAMPLE -->
</div>
</body>
<script>
function showSpinner(){
$("#spinner").addClass('slds-show').removeClass('slds-hide');
}
function hideSpinner(){
$("#spinner").addClass('slds-hide').removeClass('slds-show');
}
</script>
</html>
</apex:page>