Why can't I send a multipart/form-data request to Microsoft OneNote?

1.4k views Asked by At

I am modifying software to export client data to Microsoft OneNote instead of to local html files. I'm also not an experienced programmer, so I've been trying to teach myself this API and these protocols as I go along.

I am able to sucessfully use both the Apigee interface and hurl.it to send multipart POST requests and upload pages to a OneNote Notebook.

On hurl.it, I include two headers:

"Authorization", "myAuthCode"

"Content-Type", "multipart/form-data; boundary=NewPart"

While these interfaces work fine, I am unable to replicate the process in my Java project.

Here is my test code:

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

public class Main {


public static void main(String[] args) {

    String tokenString = "LONG_TOKEN_STRING"

    Client client = ClientBuilder.newClient();
    Entity<String> payload = Entity.text("--NewPart\n" +
            "Content-Disposition: form-data; name=\"Presentation\"\n" +
            "Content-Type: application/xhtml+xml\n" +
            "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
            "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en-us\">\n" +
            "  <head>\n" +
            ... //the rest of the POST request body is in here
            ...
            "</body></html>\n" +
            "--NewPart--\n" +
            ".\n");

    Response response = client.target("https://www.onenote.com/api/v1.0/pages")
            .request(MediaType.TEXT_PLAIN_TYPE)
            .header("Authorization", "Bearer " + tokenString)
            .header("Content-Type", "multipart/form-data; boundary=NewPart")
            .post(payload);

    System.out.println("status: " + response.getStatus());
    System.out.println("headers: " + response.getHeaders());
    System.out.println("body: \n" + response.readEntity(String.class));

    }
}

When I execute this code, I receive the following response:

"code":"20110","message":"Page create requests require the content to be multipart, with a presentation part."

From this, I know that I'm successfully contacting OneNote, and successfully authenticating.

I believe that my error is in the way I set up the headers in Java. I'm unsure if you're allowed to chain .header methods. The only other way that I'm aware of is to pass a MultiValuedMap to the .headers method, though I'm unfamiliar with the interface and how to implement it.

The OneNote Dev Center is a bit unhelpful, telling me only what I already know and seem to have included in my code.

Edit:

I've updated my code with CRLF's in place of single \n characters, though the problem persists:

Updated Java Code OneNote Error Code

2

There are 2 answers

1
Paul Samsotha On BEST ANSWER

Look at Entity.text()

Create a "text/plain" entity.

I haven't tested, but I'm guessing that this overwrites the Content-Type you set in the header() method. You can use

Entity.entity(entity, MediaType)

to create a generic entity, where you can specify the media type.

Another thing, I don't know what JAX-RS implementation you are using, but any implementation should have multipart support, so you don't to manually handle the building of the body. Here is an example using Jersey.

4
codemonk113 On

You should use CRLF \r\n instead of \n [especially when dealing with ms/windows].

It looks like you are missing a \n character at the beginning of payload and a 2nd \n after the \n on the line "Content-Type: application/xhtml+xml\n"

sources:

http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

https://www.ietf.org/rfc/rfc2046.txt

PS the rest of your code looks good