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

REST Service - Multipart Post (JSON and File) as stream on https using Jersey

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

如何使用 Jersey(用于 websphere)或 HttpClient 调用 REST 服务并将文件作为多部分发送。我想将文件作为多个不同大小的流发送,因为我们可以拥有超过 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 次。

首先,我怎样才能实现以块或多个流的形式发送大文件,而不是在一次调用中发送整个文件。其次,有没有办法避免 3 次调用服务器进行 NTLM 身份验证?

有什么指点吗?

干杯!

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

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

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

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

你基本上有两个选择:

  1. 仅使用可重复的 ContentBody 实现,例如 FileBody 或自己的可重复的 ContentBody 实例。
  2. 确保不需要重试请求。

请注意后者并非总是可行。如前所述,可以避免由于身份验证失败而导致的请求重试,但不能避免由于 I/O 错误而导致的请求重试。