REST服务 - 使用Jersey在https上作为流的多部分发布(JSON和文件)

时间:2017-06-06 09:13:09

标签: java json rest httpclient jersey-client

我在https连接上有一个REST服务,它接受文件上传为多部分(即文件和文件本身的元数据)

如何使用Jersey(用于websphere)或HttpClient调用REST服务并将文件作为multipart发送。我希望将文件作为多个不同大小的流发送,因为我们可以拥有超过1GB的文件。此外,REST服务使用Windows NT身份验证进行授权,并且位于https上。

任何人都可以举例说明我是如何实现这一目标的吗?我用过多部分httpClient。将其作为流发送不起作用。下面是我使用httpClient 4.5.2的代码

====================================

InputStream stream = new FileInputStream("test.doc");

MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setStrictMode();

InputStreamBody streamBody = new InputStreamBody(stream, docHandler.getFilename());

FormBodyPart filePart = FormBodyPartBuilder.create()
                .setName("Binary")
                .addField(Constants.RETRIEVAL_NAME_FIELD, "test.doc")               
                .addField("Content-Type",docHandler.getContentType())
                .setBody(streamBody)
                .build();
entityBuilder.addPart(filePart);

HttpPost httpPostRequest = new HttpPost();
httpPostRequest.setEntity(entityBuilder.build());

httpClient.execute(httpPostRequest);

==================================== 但是当我执行此代码时,我收到以下错误

org.apache.http.client.NonRepeatableRequestException:无法使用不可重复的请求实体重试请求

知道我为什么会收到此错误。如果我将流转换为字节数组并使用ByteArrayBody,那么它工作正常但我注意到在Fiddler中正在向服务器发出三个请求调用,并且在每次调用中都会复制文件的整个内容。因此,如果我的文件是1GB,那么整个内容将被发送到服务器三次。

首先,如何在块或多个流中实现发送大文件,以便在一次调用中不发送整个文件。其次,有没有办法避免3次调用服务器进行NTLM身份验证?

任何指针?

干杯!

1 个答案:

答案 0 :(得分:0)

发生异常是因为InputStreamBody不可重复(特别是对于大型流)。一般InputStream只能读一次。

FileBody是可重复的,因为可以多次读取文件。

可重复读取的一个原因可能是(NTLM)授权(没有检查)。

您可以通过在实际请求和设置/发送之前执行前两个NTML授权步骤来避免这种情况 Authorization: NTLM <base64-encoded type-3-message>标题,但这并不能解决问题,因为网络可能不够可靠,无论如何都必须重试。

您基本上有两个选择:

  1. 仅使用可重复的ContentBody实施,例如FileBody或拥有可重复的ContentBody实例。
  2. 确保不需要重试请求。
  3. 请注意后者并非总是可以。如前所述,可以避免由于身份验证失败而导致的请求重试,但由于I / O错误导致的重试不能。