Why can't I submit a multipart / form-data request to Microsoft OneNote?
I am modifying the software to export client data to Microsoft OneNote instead of local html files. I am not an experienced programmer either, so I tried to teach myself this API and these protocols as I go.
I can successfully use the Apigee and hurl.it interface to send multipage POST requests and load pages to OneNote notebook.
In hurl.it, I include two headers:
"Authorization", "myAuthCode"
"Content-Type", "multipart / form-data; border = NewPart"
While these interfaces work fine, I cannot 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 get the following response:
"code": "20110", "message": "Requests to create a page require content to be multipart, with part of the presentation."
From this I know that I am successfully communicating with OneNote and successfully authenticating.
I believe my mistake is the way I set up the headers in Java. I'm not sure if you are allowed to use the .header methods. The only other way I know of is to pass the MultiValuedMap to the .headers method, although I'm not familiar with the interface and how to implement it.
The OneNote Dev Center is a bit gimmicky, telling me only what I already know and seem to have included in my code.
Edit:
I updated my code with CRLF instead of single \ n characters, although the problem persists:
source to share
Take a look Entity.text()
Create a "text / plain" object.
I have not tested, but I am guessing it overwrites the Content-Type
one set in the method header()
. you can use
Entity.entity(entity, MediaType)
to create a shared object where you can specify the media type.
Another thing is, I don't know which JAX-RS implementation you are using, but any implementation should have multiple access support, so you don't have to manually handle body building. Here is an example using Jersey .
source to share
You should use CRLF\r\n
instead \n
[especially when working with ms / windows].
It looks like you are missing the character \n
at the beginning payload
and 2nd \n
after \n
in the string"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
source to share