You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Olingo OData4客户端生成批量文件上传的multipart/mixed请求体?

使用Olingo客户端API生成OData批量Multipart文件上传请求

问题背景

已通过Postman实现Apache Olingo OData批量处理中的multipart请求体文件上传,现在需要用Olingo客户端API生成完全一致的请求(类似Apache HTTPClient的MultipartEntityBuilder功能)。

Postman中可正常运行的批量请求

请求地址:

https://hostname:443/MyApp/servlet/odata/MyDomain/$batch

请求头:

Content-Type: multipart/mixed;boundary=batch_50f02a08-698b-4af0-b19a-1fcb75d244d8

Postman原始请求体

--batch_50f02a08-698b-4af0-b19a-1fcb75d244d8
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-ID:1

PUT https://hostname:443/MyApp/servlet/odata/MyDomain/Documents('OID:my.doc.Document:12345')/MyContent/$value HTTP/1.1
Accept: */*
Content-Type: multipart/form-data; boundary=ContentSeparator
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-ID: 1

--ContentSeparator
Content-Disposition: form-data; name="myFilepathInput";filename="myFile1.txt"
Content-Type: text/plain

Hello, World!
This is a text file.

--ContentSeparator--

--batch_50f02a08-698b-4af0-b19a-1fcb75d244d8--

尝试过的两种方法及问题

需要生成的核心multipart分段部分:

--ContentSeparator
Content-Disposition: form-data; name="myFilepathInput";filename="myFile1.txt"
Content-Type: text/plain

Hello, World!
This is a text file.

--ContentSeparator--

方法1:使用ODataEntityUpdateRequest

伪代码:

ODataClient client = ODataClientFactory.getClient();
ODataBatchRequest req = client.getBatchRequestFactory().getBatchRequest(batchBaseURI.toString());
BatchManager payloadManager = batchRequest.payloadManager();
// 省略无关代码..
File file = new File(filepath.toString());
ClientEntity entity = client.getObjectFactory().newEntity(qualifiedName);
// 省略无关代码...
entity.setMediaContentSource(file.toURI());
entity.setMediaContentType(ContentType.parse("text/html").toContentTypeString());
entity.setMediaEntity(true);

URI insertUri = // PUT请求URI,省略无关代码...

CUDRequestFactory requestFactory = client.getCUDRequestFactory();
ODataEntityUpdateRequest<ClientEntity> updateRequest = requestFactory.getEntityUpdateRequest(insertUri, UpdateType.REPLACE, entity);
updateRequest.setContentType("multipart/form-data");
// 省略无关代码...
payloadManager.addRequest(updateRequest);

生成的请求体问题:文件信息以JSON格式呈现,而非标准multipart分段结构:

--batch_a4ac4cb0-c851-4767-a043-e7df8b24e0fb
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID:1

PUT https://hostname:443/MyApp/servlet/odata/MyDomain/Documents('OID:my.doc.Document:12345')/MyContent/$value HTTP/1.1
Accept: */*
Content-Type: multipart/form-data
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-ID: 1

{"FileName":"myFile1.txt","filePath":"D:/temp/myFile1.txt"}
--batch_a4ac4cb0-c851-4767-a043-e7df8b24e0fb—

方法2:使用ODataMediaEntityUpdateRequest

伪代码:

ODataClient client = ODataClientFactory.getClient();
InputStream targetStream = new FileInputStream(file);
ClientEntity entity = client.getObjectFactory().newEntity(qualifiedName);
// 省略无关代码...

URI insertUri = // PrimaryContent的PUT请求URI,省略无关代码...

CUDRequestFactory requestFactory = client.getCUDRequestFactory();
ODataMediaEntityUpdateRequest<ClientEntity> updateMediaRequest = requestFactory.getMediaEntityUpdateRequest(insertUri, targetStream);
updateMediaRequest.setContentType("multipart/form-data");
payloadManager.addRequest(updateMediaRequest);

生成的请求体问题:仅包含文件内容,缺少文件元信息和独立的multipart boundary分段:

--batch_fc2c9fc0-4a9b-44cf-a7c1-84aabff2e106
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID:1

PUT https://hostname:443/MyApp/servlet/odata/MyDomain/Documents('OID:my.doc.Document:12345')/MyContent/$value HTTP/1.1
Accept: */*
Content-Type: multipart/form-data
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-ID: 1

Hello, World!
This is a text file.
--batch_fc2c9fc0-4a9b-44cf-a7c1-84aabff2e106--

解决方案

要生成符合要求的请求,需手动构建multipart/form-data请求体,再将其作为批量请求的子请求内容,步骤如下:

  1. 构建内部multipart/form-data请求体
    借助Apache HttpClient的MultipartEntityBuilder构建标准文件上传分段:
MultipartEntityBuilder multipartBuilder = MultipartEntityBuilder.create();
multipartBuilder.setBoundary("ContentSeparator");
// 添加文件及元信息
multipartBuilder.addBinaryBody(
    "myFilepathInput",
    new File("D:/temp/myFile1.txt"),
    ContentType.TEXT_PLAIN,
    "myFile1.txt"
);
HttpEntity multipartEntity = multipartBuilder.build();
  1. 将multipart内容转换为InputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
multipartEntity.writeTo(baos);
InputStream multipartStream = new ByteArrayInputStream(baos.toByteArray());
  1. 创建批量请求并添加子请求
    通过Olingo的原始请求API,将构建好的multipart流作为请求体:
ODataClient client = ODataClientFactory.getClient();
ODataBatchRequest batchRequest = client.getBatchRequestFactory().getBatchRequest("https://hostname:443/MyApp/servlet/odata/MyDomain/$batch");
BatchManager payloadManager = batchRequest.payloadManager();

// 构造PUT子请求
URI putUri = new URI("https://hostname:443/MyApp/servlet/odata/MyDomain/Documents('OID:my.doc.Document:12345')/MyContent/$value");
ODataRawRequest rawPutRequest = client.getRawRequestFactory().getRawRequest(HttpMethod.PUT, putUri);
// 设置请求头
rawPutRequest.setHeader("Accept", "*/*");
rawPutRequest.setHeader("Content-Type", "multipart/form-data; boundary=ContentSeparator");
rawPutRequest.setHeader("OData-MaxVersion", "4.0");
rawPutRequest.setHeader("OData-Version", "4.0");
rawPutRequest.setHeader("Content-ID", "1");
// 设置请求体
rawPutRequest.setRequestEntity(multipartStream, multipartEntity.getContentLength());

// 加入批量请求
payloadManager.addRequest(rawPutRequest);

// 执行请求并处理响应
ODataBatchResponse batchResponse = batchRequest.execute();
// 响应处理逻辑...

此方式生成的批量请求体与Postman中的完全一致。


内容的提问来源于stack exchange,提问作者Rohit Gaikwad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:42:00