在使用PipedInputStream作为ContentBody

时间:2019-07-30 11:45:19

标签: java apache-httpclient-4.x apache-httpcomponents

我正在尝试将多部分请求发送到服务器。这样做时,我正在使用PipedOutputStream和PipedInputStream分别生成和使用数据。接着在MultipartEntityBuilder类中将PipedInputStream用作二进制正文内容。

请求进入阻塞状态-projectModelFuture.isDone()始终为false。

public class MyStreamItemOutputStream
    implements StreamItemOutputStream {

  private PipedOutputStream pipedOut = new PipedOutputStream();
  private PipedInputStream pipedIn;
  private Future<ProjectModel> projectModelFuture;
  private ExecutorService es = Executors.newSingleThreadExecutor();

  MyStreamItemOutputStream(MyClient myClient, ProjectModel projectModel) {
    try {
      pipedIn = new PipedInputStream(pipedOut, 8*1024);
      projectModelFuture = es.submit(() -> myClient.createProject(pipedIn, projectModel));
    } catch (Exception e) {
      System.out.println("stream.failed="+e.getMessage());
      throw e;
    }
  }

  @Override
  public void write(byte[] b, int off, int len) throws IOException {
    pipedOut.write(b, off, len);
  }

  @Override
  public void close() throws IOException {
    try {
      while (!projectModelFuture.isDone()) {
        System.out.println("===IN-PROGRESS===");
        Thread.sleep(5000);
      }

      ProjectModel createdProject = projectModelFuture.get();
    } catch (Exception e) {
      System.out.println("stream.failed="+e.getMessage());
      throw e;
    } finally {
      pipedOut.close();
      pipedIn.close();
      es.shutdown();
    }
  }
}

public class MyClient
    implements Closeable {

  private CloseableHttpClient client;
  Map<String, String> options;

  public DataRobotClient(Map<String, String> options) {
    this.options = options;

    client = // create httpclient..
  }


  public ProjectModel createProject(InputStream in, ProjectModel projectModel) {

    ResponseHandler<ProjectModel> responseHandler = response -> {
      final StatusLine statusLine = response.getStatusLine();
      final String entity = EntityUtils.toString(response.getEntity());

      if (StatusLineUtils.isSuccess(statusLine)) {
        System.out.println("Success!! " + entity);
      } else {
        System.out.println("Failed!! " + statusLine);
      }
    };

    try {
      MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
      if (!Strings.isNullOrEmpty(projectModel.getProjectName())) {
        entityBuilder.addTextBody("projectName", projectModel.getProjectName());
      }
      entityBuilder.addBinaryBody("file", in, ContentType.create("text/csv"), projectModel.getFileName());

      // MultipartRequestBuilder is a custom class
      return client.execute(
          MultipartRequestBuilder.post("/projects/")
                                 .setEntity(entityBuilder.build())
                                 .setHeader(HttpHeaders.AUTHORIZATION, "Token xxxsomeTokenGoesHerexxx")
                                 .build(),
          responseHandler);
    } catch (Exception ce) {
      throw ce;
    }
  }
}

我的期望是PipedOutputStream将数据写入管道,而PipedInputStream将读取数据块,从而消除了内存不足的可能性。

注意:我已经使用ByteArrayOutputStream成功实现了相同的功能,但是它获得的OOM具有大数据。

0 个答案:

没有答案