从S3直接将文件流式传输到响应

时间:2018-04-17 14:42:51

标签: amazon-s3 jersey dropwizard

我有以下代码作为S3存储桶的网关。这样做的目的是下载位于S3上的文件但不暴露S3项链接。 一切正常,但在大约50次下载后,我们不断获得Timeout waiting for connection from pool例外。 我发现这可能是由于没有关闭s3Object.getObjectContent()造成的,但正如您可以看到我正在使用"尝试使用资源"这可确保调用close()。我不仅要在流上做这个,还要对对象本身这样做。这是最后的手段,因为它不会改变任何东西。事实上,S3Object.close()做同样的事情 - 关闭底层的InputStream。

当我手动测试时,我可以看到正在调用close()

@GET
@Produces({MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON})
@Path("/{id}/download")

public Response download(@NotNull @PathParam("id") String id) {
    return repository.get()
        .map(record -> Response.status(OK)
            .header(HttpHeaders.CONTENT_DISPOSITION, "...")
            .entity((StreamingOutput) outputStream -> {
                try (S3Object s3Object = s3Service.getObject(record.getS3Key());
                    InputStream inputStream = s3Object.getObjectContent()) {

                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                        outputStream.flush();
                    }
                    outputStream.flush();
                }
            })
            .build())
        .orElseThrow(() -> new EntityNotFoundException(String.format("Could not find download id: %s", id)));
}

[编辑]

  • AWS S3 java lib版本1.11.308
  • AmazonS3设置为单身

1 个答案:

答案 0 :(得分:1)

似乎您必须在关闭流is.skip(Long.MAX_VALUE)之前对其进行调用。

try (InputStream is =new DrainOnCloseInputStream(s3Object.getObjectContent())) {
            processFile(is,fileExt, context, logGroupName, logStreamName);
}

public class DrainOnCloseInputStream extends FilterInputStream {
    public DrainOnCloseInputStream(InputStream paramInputStream) {
        super(paramInputStream);
    }

    @Override
    public void close() throws IOException {
        drain(in);
        super.close();
    }

    private static void drain(InputStream is) throws IOException {
        is.skip(Long.MAX_VALUE);
    }
}