如何在 body 与 Java 的请求中创建 multipart/mixed 与 xml 的请求?

How to create multipart/mixed request with xml in the request body with Java?

下面是我想用 JAVA 创建的一个请求。 但在第一部分,我想放置 XML,而不是字段或文本,而是 XML,在第二部分 - 我要上传的文件。此外,我请求的每一部分都应该有不同的内容类型和内容配置。

那么如何为请求中的不同部分设置不同的 HTTP headers?

另外一个问题是:你能解释一下 Content-Disposition 到底是什么以及什么时候使用它吗?

--boundary-string
Content-Disposition: name="request_payload"
Content-Type: text/xml

<tsRequest>
    <datasource name="datasource-name" >
        <connectionCredentials name="connection-username" password="connection-password"
            embed="embed-flag" />
        <project id="project-id" />
  </datasource>
</tsRequest>
--boundary-string
Content-Disposition: name="tableau_datasource"; filename="datasource-file-name"
Content-Type: application/octet-stream

content-of-datasource-file
--boundary-string--

我想我看到了一些东西,但我不知道如何将我的 content-disposition 放入零件中。这是我的代码:

    HttpClient client = HttpClientBuilder.create().build();

    File file = new File("D:/qwe.txt");
    HttpPost post = new HttpPost("https://test.com/datasources");
    post.setHeader("X-Tableau-Auth", "RfVJIasdsadrW");
    StringBody stringBody1 = new StringBody("The XML body is here!", ContentType.APPLICATION_XML);
    FileBody fileBody = new FileBody(file, ContentType.APPLICATION_OCTET_STREAM);


    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    builder.addPart("text1", stringBody1);
    builder.addPart("upfile", fileBody);

    HttpEntity entity = builder.build();

    post.setEntity(entity);
    HttpResponse response = client.execute(post);
    System.out.println(response);

这里怎么写Content-Disposition:name="tableau_datasource";文件名="datasource-file-name"?

我的意思是,使用随您选择的语言提供的任何 HTTP 客户端 API 的多部分功能。您有点需要告诉您尝试使用哪种语言发送。但是任何有价值的 HTTP 客户端 API 都会提供这样做的可能性,而无需询问如何去做。

编辑:所以语言是 Java。使用 Apache's HttpClient 4.5 发送多部分请求相当容易。请参阅随附的示例。

编辑 2:抱歉。事实证明,毕竟通过查看示例并不能证明它是显而易见的。我发誓我记得是这样的。

假设你有:

String document;
byte[] file;

您可以通过以下方式提出此请求:

HttpEntity entity = MultipartEntityBuilder.create()
  .setMimeSubtype("mixed")
  .addPart(FormBodyPartBuilder.create()
    .setName("request_payload")
    .setBody(new StringBody(document, ContentType.create("text/xml")))
    .build())
  .addPart(FormBodyPartBuilder.create()
    .setName("tableau_datasource")
    .setBody(new ByteArrayBody(file, "datasource-file-name"))
    .build())
  .build();

HttpPost request = new HttpPost("http://localhost:1337/test");
request.setEntity(entity);

client.execute(new HttpHost("localhost", PORT), request);

产生:

POST /test HTTP/1.1
Content-Length: 410
Content-Type: multipart/mixed; boundary=xA-V-5psFZxuuisERy1jKEcqzo4vYI6Kq
Host: localhost:1337
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_144)
Accept-Encoding: gzip,deflate

--xA-V-5psFZxuuisERy1jKEcqzo4vYI6Kq
Content-Disposition: form-data; name="request_payload"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit

<... the doc ...>
--xA-V-5psFZxuuisERy1jKEcqzo4vYI6Kq
Content-Disposition: form-data; name="tableau_datasource"; filename="datasource-file-name"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

<... the file ...>
--xA-V-5psFZxuuisERy1jKEcqzo4vYI6Kq--

这应该足够接近并以与您的请求相同的方式被接受。有需要可以fine-tune

Additional question is: could you explain me what exactly is Content-Disposition and when it is used ?

一般来说,它有助于提供有关多部分当前部分的信息,这些信息只有在处于多部分的上下文中才真正有意义。

示例:给 name 部分,这样您就可以判断该部分是否包含您的 XML 文档或它是否包含您正在上传的文件(哪个也可以是 XML 文件。)

其他示例,如果通常要将其存储为文件,则指示该部分的首选 文件名

它最常见的用法是发送带有输入文件的常规 HTML 表单。这些作为 multipart/form-data 发送,每个部分都有一个

Content-Disposition: form-data; name="name of the field defined in the HTML form"

并且文件有

Content-Disposition: form-data; name="name of the input file field"; filename="filename.ext"

请注意,Content-Disposition header 必须 以指示零件性质的标记开头。 HTML 形式是 form-data,在其他任何地方你都可以使用 attachment。您也可以定义自己的,因为从技术上讲,发送像这样的多部分消息而不是 HTML 表单或 SOAP 请求,不是标准化的,因此客户端和服务器将需要遵守为其创建的规范.

如果我们使用 MultipartEntityBuilder.create() 这将始终对数据进行编码 例如:创建如下所示的多部分将对 xml 和文件

进行编码
 String document = "<tsRequest>
    <datasource name="datasource-name" >
        <connectionCredentials name="connection-username" password="connection-password"
            embed="embed-flag" />
        <project id="project-id" />
  </datasource>
</tsRequest>
HttpEntity entity = MultipartEntityBuilder.create()
  .setMimeSubtype("mixed")
  .addPart(FormBodyPartBuilder.create()
    .setName("request_payload")
    .setBody(new StringBody(document, ContentType.create("text/xml")))
    .build())
  .addPart(FormBodyPartBuilder.create()
    .setName("tableau_datasource")
    .setBody(new ByteArrayBody(file, "datasource-file-name"))
    .build())
  .build();

虽然我们在这里发送 ContentType.create("text/xml") StringBody class 正在对其进行编码并发送到服务器。我看到您正在调用 tableau 服务器,tableau 将接受 xml。

Tableau 文档如下所示 注意:发布的内容不应进行编码(例如,使用 Base-64 或 UTF-8)。 请查看此文档:https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_publish.htm

找到有效的球衣客户端。要推送到画面服务器的示例球衣客户端项目:https://github.com/tableau/rest-api-samples