为什么我不能向 Microsoft OneNote 发送 multipart/form-data 请求?
Why can't I send a multipart/form-data request to Microsoft OneNote?
我正在修改软件以将客户端数据导出到 Microsoft OneNote 而不是本地 html 文件。我也不是一个有经验的程序员,所以我一直在努力自学这个API和这些协议。
我能够成功地使用 the Apigee interface and hurl.it 发送多部分 POST 请求并将页面上传到 OneNote 笔记本。
在 hurl.it 上,我包括两个 header:
"Authorization"、"myAuthCode"
"Content-Type"、"multipart/form-data; boundary=NewPart"
虽然这些接口工作正常,但我无法在我的 Java 项目中复制该过程。
这是我的测试代码:
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));
}
}
当我执行这段代码时,我收到以下响应:
"code":"20110","message":"Page create requests require the content to be multipart, with a presentation part."
由此,我知道我已经成功联系到OneNote,并且认证成功。
我认为我的错误在于我在 Java 中设置 header 的方式。我不确定您是否可以链接 .header 方法。我知道的唯一其他方法是将 MultiValuedMap 传递给 .headers 方法,尽管我不熟悉该接口以及如何实现它。
OneNote 开发中心有点无用,它只告诉我我已经知道并且似乎包含在我的代码中的内容。
编辑:
我已经用 CRLF 代替单个 \n 字符更新了我的代码,但问题仍然存在:
您应该使用 CRLF \r\n
而不是 \n
[尤其是在处理 ms/windows] 时。
您似乎在 payload
开头缺少 \n
字符,在 \n
之后缺少 2nd \n
=] 在线 "Content-Type: application/xhtml+xml\n"
来源:
http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
https://www.ietf.org/rfc/rfc2046.txt
PS 您的其余代码看起来不错
Create a "text/plain" entity.
我没有测试过,但我猜测这会覆盖您在 header()
方法中设置的 Content-Type
。您可以使用
Entity.entity(entity, MediaType)
创建通用实体,您可以在其中指定媒体类型。
另一件事,我不知道您使用的是什么 JAX-RS 实现,但任何实现都应该具有多部分支持,因此您不必手动处理正文的构建。 Here is an example using Jersey.
我正在修改软件以将客户端数据导出到 Microsoft OneNote 而不是本地 html 文件。我也不是一个有经验的程序员,所以我一直在努力自学这个API和这些协议。
我能够成功地使用 the Apigee interface and hurl.it 发送多部分 POST 请求并将页面上传到 OneNote 笔记本。
在 hurl.it 上,我包括两个 header:
"Authorization"、"myAuthCode"
"Content-Type"、"multipart/form-data; boundary=NewPart"
虽然这些接口工作正常,但我无法在我的 Java 项目中复制该过程。
这是我的测试代码:
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));
}
}
当我执行这段代码时,我收到以下响应:
"code":"20110","message":"Page create requests require the content to be multipart, with a presentation part."
由此,我知道我已经成功联系到OneNote,并且认证成功。
我认为我的错误在于我在 Java 中设置 header 的方式。我不确定您是否可以链接 .header 方法。我知道的唯一其他方法是将 MultiValuedMap 传递给 .headers 方法,尽管我不熟悉该接口以及如何实现它。
OneNote 开发中心有点无用,它只告诉我我已经知道并且似乎包含在我的代码中的内容。
编辑:
我已经用 CRLF 代替单个 \n 字符更新了我的代码,但问题仍然存在:
您应该使用 CRLF \r\n
而不是 \n
[尤其是在处理 ms/windows] 时。
您似乎在 payload
开头缺少 \n
字符,在 \n
之后缺少 2nd \n
=] 在线 "Content-Type: application/xhtml+xml\n"
来源:
http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
https://www.ietf.org/rfc/rfc2046.txt
PS 您的其余代码看起来不错
Create a "text/plain" entity.
我没有测试过,但我猜测这会覆盖您在 header()
方法中设置的 Content-Type
。您可以使用
Entity.entity(entity, MediaType)
创建通用实体,您可以在其中指定媒体类型。
另一件事,我不知道您使用的是什么 JAX-RS 实现,但任何实现都应该具有多部分支持,因此您不必手动处理正文的构建。 Here is an example using Jersey.