当输入流开始读取时,输出流开始写入

Outputstream start writing when inputstream starts reading

我想通过 http 发送一个大对象(比如说 4G)。

我们有一个自定义序列化程序,可以将对象写入 OutputStream。目前我们将对象写入磁盘并将该文件用于用于请求的输入流。

类似于这些行:

private static Response sendObject(Object bigObject) throws IOException {
  File tempFile = File.createTempFile("x", "y");
  OutputStream out = new FileOutputStream(tempFile);
  CustomSerializer.serialize(bigObject, out);
  out.close();

  WebTarget resource = service.path("data");

  FormDataMultiPart multiPartEntity = new FormDataMultiPart();

  InputStream inputStream = new FileInputStream(tempFile);
  StreamDataBodyPart streamBodyPart = new StreamDataBodyPart(
        "data",
        inputStream,
        "data",
        MediaType.APPLICATION_OCTET_STREAM_TYPE);

  MultiPart multiPart = multiPartEntity.bodyPart(streamBodyPart);
  return resource.request(MediaType.APPLICATION_JSON_TYPE)
        .post(Entity.entity(multiPart, multiPart.getMediaType()));
 }

我们节省了一些内存,因为我们没有序列化到内存中的字节数组。那很好。但是我可以在不写入磁盘的情况下保存内存吗?

你能不重写 CustomSerializer 直接写入输入流吗?

你能在读入请求时直接写入输入流吗?

-

有点难以解释,但我想我在寻找类似这样的伪代码:

private static Response sendObject(Object bigObject) throws IOException {
  WebTarget resource = service.path("data");

  FormDataMultiPart multiPartEntity = new FormDataMultiPart();

  // A type of stream I don't know if exist
  OutputStream outIn = new OutputInputStream() {
     public void openInputStream() {
        CustomSerializer.serialize(bigObject, this);
     }
  };
  StreamDataBodyPart streamBodyPart = new StreamDataBodyPart(
        "data",
        outIn.getInputStream(),
        "data",
        MediaType.APPLICATION_OCTET_STREAM_TYPE);

  MultiPart multiPart = multiPartEntity.bodyPart(streamBodyPart);
  return resource.request(MediaType.APPLICATION_JSON_TYPE)
        .post(Entity.entity(multiPart, multiPart.getMediaType()));
} 

您可以使用 StreamingOutput 并使用您的 CustomSerializer 写入提供的 OutputStream

StreamingOutput entity = new StreamingOutput() {
    @Override
    public void write(OutputStream out)
            throws IOException, WebApplicationException {

        CustomSerializer.serialize(bigObject, out);
    }
};

Jersey 将调用 write() 方法,让您有机会直接写入响应实体流。

那就用一个FormDataBodyPart

BodyPart bigPart = new FormDataBodyPart(
        "data", entity, MediaType.APPLICATION_OCTET_STREAM_TYPE);
MultiPart multiPart = new FormDataMultiPart().bodyPart(bigPart);