为什么我不能向 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 您的其余代码看起来不错

看看Entity.text()

Create a "text/plain" entity.

我没有测试过,但我猜测这会覆盖您在 header() 方法中设置的 Content-Type。您可以使用

Entity.entity(entity, MediaType)

创建通用实体,您可以在其中指定媒体类型。

另一件事,我不知道您使用的是什么 JAX-RS 实现,但任何实现都应该具有多部分支持,因此您不必手动处理正文的构建。 Here is an example using Jersey.