Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microsoft graph : Updating a document with a Put request Java

Based on the MS graph documentation, I saw that i can update a driveItem (file) and put it in a specific sharepoint drive. The application is running as a daemon application (without user login).

For this I use this entry point :

PUT /drives/{drive-id}/items/{item-id}/content

I try to code using a main class and passing existing parameters. To update a document I call a method update document :

UpdateDocumentResponseModel updatedDocument = fileGraphs.updateDocument(token, DRIVELIBID, DOCUMENTID, INPUTPATH, DOCUPDATE);

The called method aims to build the URL and prepare the datas for the PUT request :

public UpdateDocumentResponseModel updateDocument(String accessToken,
                                                  String driveLibId,
                                                  String documentId,
                                                  String inpuPath,
                                                  String docName) throws MalformedURLException {
    String fullPath = inpuPath + docName;
    URL url = new URL("https://graph.microsoft.com/v1.0/drives/" + driveLibId + "/items/" + documentId + "/content");
    return requestsBuilder.updateDocument(accessToken, url, fullPath);
}

Now at this stage I have to make the request:

public UpdateDocumentResponseModel updateDocument(String accessToken, URL url, String fullPath) {
    UpdateDocumentResponseModel returnValue = new UpdateDocumentResponseModel();

    try {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPut httpPut = new HttpPut(String.valueOf(url));
        httpPut.setHeader("Authorization", "Bearer " + accessToken);
        httpPut.setHeader("Accept","application/json");
        httpPut.setHeader("Content-Type","plain/text");
        httpPut.setHeader("Connection", "Keep-Alive");
        httpPut.setHeader("Cache-Control", "no-cache");

        // read the file and convert to stream
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody("file", new File(fullPath),
                ContentType.APPLICATION_OCTET_STREAM, "file.ext");
        HttpEntity multipart = builder.build();
        httpPut.setEntity(multipart);
        CloseableHttpResponse response = client.execute(httpPut);


        System.out.println("\nSending 'UPDATE' request to URL : " + url);
        System.out.println("Response Code : " + response.getStatusLine());

        // set the response
        returnValue.setDocumentName(fullPath);
        returnValue.setUpdatedAt(new Date());
        returnValue.setUpdateStatus("Success");
    } catch (IOException e) {
        returnValue.setDocumentName(fullPath);
        returnValue.setUpdatedAt(new Date());
        returnValue.setUpdateStatus("Failure" + e.getCause());
        e.printStackTrace();
    }

    return returnValue;

}

My issue is that when I send back a docx file, this file is not correctly uploaded. The file is uploaded (good stuff) but is not readable in the sharepoint online portal and must be downloaded. My second issue is that I can take any kind of file : doc, docx, ppt, xls, xlsx, txt, images...

I do think that I will encounter other issues. Is there a lib that could help me to handle file extension and correctly convert files. My issue is that I won't have to handle specifically MS Office files but any types.

My issue is obviously here :

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File(fullPath),
   ContentType.APPLICATION_OCTET_STREAM, "file.ext");
HttpEntity multipart = builder.build();
httpPut.setEntity(multipart);
CloseableHttpResponse response = client.execute(httpPut);

Thanks !

like image 818
davidvera Avatar asked Mar 05 '20 09:03

davidvera


1 Answers

I finally solved the issue by using ByteArrayInputStream...

I replaced :

// read the file and convert to stream
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File(fullPath),
       ContentType.APPLICATION_OCTET_STREAM, "file.ext");
HttpEntity multipart = builder.build();
httpPut.setEntity(multipart);

with this:

byte[] fileContent = FileUtils.readFileToByteArray(new File(fullPath));
httpPut.setEntity(new InputStreamEntity(new ByteArrayInputStream(fileContent), fileContent.length));

Finally my method looks like this :

public UpdateDocumentResponseModel updateDocument(String accessToken, URL url, String fullPath) {
    UpdateDocumentResponseModel returnValue = new UpdateDocumentResponseModel();

    try {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPut httpPut = new HttpPut(String.valueOf(url));
        httpPut.setHeader("Authorization", "Bearer " + accessToken);
        httpPut.setHeader("Content-Type", "text/plain");
        httpPut.setHeader("Connection", "Keep-Alive");
        httpPut.setHeader("Cache-Control", "no-cache");

        byte[] fileContent = FileUtils.readFileToByteArray(new File(fullPath));
        httpPut.setEntity(new InputStreamEntity(new ByteArrayInputStream(fileContent), fileContent.length));

        // httpPut.setEntity(new StringEntity(String.valueOf(in), StandardCharsets.UTF_8));
        CloseableHttpResponse response = client.execute(httpPut);

        System.out.println("\nSending 'PUT' request to URL : " + url);
        System.out.println("Response Code : " + response.getStatusLine());

        // set the response
        returnValue.setDocumentName(fullPath);
        returnValue.setUpdatedAt(new Date());
        returnValue.setUpdateStatus("Success");
    } catch (IOException e) {
        returnValue.setDocumentName(fullPath);
        returnValue.setUpdatedAt(new Date());
        returnValue.setUpdateStatus("Failure" + e.getCause());
        e.printStackTrace();
    }
    return returnValue;
}
like image 145
davidvera Avatar answered Oct 25 '22 16:10

davidvera