如何用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请求体,再将其作为批量请求的子请求内容,步骤如下:
- 构建内部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();
- 将multipart内容转换为InputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream(); multipartEntity.writeTo(baos); InputStream multipartStream = new ByteArrayInputStream(baos.toByteArray());
- 创建批量请求并添加子请求
通过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
相关产品推荐
相关产品推荐

