To anyone looking for a Java implementation using RestTemplate
:
I figured out how to upload a file to Sharepoint, since I had the same necessity.
First of all, we need to retrieve our Bearer Token:
SharepointResponse class
@Getter
@Setter
public class SharepointResponse {
@JsonProperty("token_type")
private String tokenType;
@JsonProperty("expires_in")
private int expiration;
@JsonProperty("ext_expires_in")
private int extExpiration;
@JsonProperty("access_token")
private String accessToken;
}
Imports and global variables/constants
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@Autowired
RestTemplate restTemplate;
@Value("${tenant-id}") // you can retrieve them from application.properties
private String tenantId;
@Value("${client-id}")
private String clientId;
@Value("${client-secret}")
private String clientSecret;
@Value("${site-id}")
private String siteId;
private static final int CHUNK_SIZE = 5 * 1024 * 1024;
Code snippet
String url = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED));
headers.set(
"Authorization",
"Basic " + new String(
Base64.encodeBase64(
(clientId + ":" + clientSecret)
.getBytes(StandardCharsets.US_ASCII)
)
)
);
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "client_credentials");
body.add("scope", "https://graph.microsoft.com/.default");
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(body, headers);
ResponseEntity<SharepointResponse> response = restTemplate.exchange(url, HttpMethod.POST, entity, SharepointResponse.class);
if (response.getStatusCodeValue() == 200) {
String token = response.getBody().getAccessToken();
doUpload(token);
} else {
// DO SOMETHING - retrieving token failed
}
Now, we need the Site Id. We can retrieve it by performing a GET at this endpoint:
https://graph.microsoft.com/v1.0/sites/<YOUR_HOST.sharepoint.com>:/sites/<YOUR_SITE>?$select=id
We need to put a Bearer Authentication
header, with the token we retrieved earlier.
After that, we have two choices:
- Perform a PUT request to
https://graph.microsoft.com/v1.0/sites/<YOUR_SITE_ID>/drive/root:/<OUTPUT_FILE_NAME>:/content
NOTE, the maximum upload size is 4MB!
- Perform a POST request to
https://graph.microsoft.com/v1.0/sites/<YOUR_SITE_ID>/drive/root:/<OUTPUT_FILE_NAME>:/createUploadSession
and then perform a PUT request to the uploadUrl
we obtained earlier
In the Java code below, I will show you the second option.
doUpdate() method
public void doUpdate(String token){
String fileName = "output_file_name.txt";
String sessionCreationUrl = "https://graph.microsoft.com/v1.0/sites/" + siteId + "/drive/root:/" + fileName + ":/createUploadSession";
String sessionUrl = createUploadSession(token, sessionCreationUrl);
if (sessionUrl != null) {
uploadFile(sessionUrl, "/path/to/file_to_upload", token);
} else {
// DO SOMETHING - creating session failed
}
}
createUploadSession() method
private String createUploadSession(String accessToken, String url){
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
// Request body for creating upload session
Map<String, Object> body = Collections.emptyMap();
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<Map> response = restTemplate.postForEntity(url, requestEntity, Map.class);
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return (String) response.getBody().get("uploadUrl");
}
return null;
}
uploadFile() method
private void uploadFileInChunks(String sessionUrl, String filePath, String accessToken) throws IOException {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[CHUNK_SIZE];
long fileSize = file.length();
long bytesRemaining = fileSize;
long offset = 0;
while (bytesRemaining > 0) {
int bytesRead = fis.read(buffer, 0, CHUNK_SIZE);
if (bytesRead <= 0) {
break;
}
byte[] chunk = new byte[bytesRead];
System.arraycopy(buffer, 0, chunk, 0, bytesRead);
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// Set the content range header
String contentRange = "bytes " + offset + "-" + (offset + bytesRead - 1) + "/" + fileSize;
headers.set("Content-Range", contentRange);
HttpEntity<byte[]> chunkEntity = new HttpEntity<>(chunk, headers);
ResponseEntity<String> response = restTemplate.exchange(sessionUrl, HttpMethod.PUT, chunkEntity, String.class);
if (!response.getStatusCode().is2xxSuccessful()) {
// DO SOMETHING - upload failed
}
offset += bytesRead;
bytesRemaining -= bytesRead;
}
fis.close();
}
This was also answered on Stack Overflow, at this link.