如何将HttpResponse保存为本地PDF及解决流关闭读取异常
解决HttpResponse读取PDF时"Attempted read from closed stream"异常问题
我之前也踩过这个坑!这个异常的核心原因是你直接获取的InputStream被HttpClient提前关闭了——因为HttpClient的连接池会在实体未被完全消费时,自动回收连接并关闭关联的流,尤其是当你没有正确处理HttpEntity的时候。
你的原代码里直接调用secondResponse.getEntity().getContent()获取流,但这个流是和底层HTTP连接绑定的,一旦连接被回收,流就会被关闭,导致读取时抛出异常。另外,原代码也没有正确关闭资源,这也可能加剧问题。
下面给你几个靠谱的解决方案:
方案1:用IOUtils安全拷贝流(推荐)
Apache Commons IO里的IOUtils.copy方法会帮你处理流的读取和关闭,避免手动操作出错:
import org.apache.commons.io.IOUtils; HttpResponse secondResponse = aHttpClient.execute(secondPost); HttpEntity entity = secondResponse.getEntity(); if (entity != null) { FileOutputStream fileOutputStream = new FileOutputStream(new File("Result.pdf")); try { IOUtils.copy(entity.getContent(), fileOutputStream); } finally { // 确保关闭所有资源 IOUtils.closeQuietly(fileOutputStream); IOUtils.closeQuietly(entity.getContent()); // 或者用EntityUtils.consume(entity)来确保实体被正确消费 EntityUtils.consume(entity); } }
方案2:手动处理实体,确保连接不被提前回收
如果你不想用第三方工具类,可以先把实体内容读取到字节数组里,再写入文件——这样流就和连接解绑了:
HttpResponse secondResponse = aHttpClient.execute(secondPost); HttpEntity entity = secondResponse.getEntity(); if (entity != null) { // 先把实体内容读到字节数组 byte[] pdfBytes = EntityUtils.toByteArray(entity); FileOutputStream fileOutputStream = new FileOutputStream(new File("Result.pdf")); try { fileOutputStream.write(pdfBytes); } finally { fileOutputStream.close(); // 消费实体,避免连接泄漏 EntityUtils.consume(entity); } }
关键注意点
- 永远不要直接持有
entity.getContent()返回的流并长时间使用,它和底层连接绑定,随时可能被关闭 - 不管用哪种方式,都要确保调用
EntityUtils.consume(entity)或者关闭流,这样HttpClient才能正确回收连接 - 记得用try-finally或者try-with-resources(Java 7+)来自动关闭输出流,避免资源泄漏
内容的提问来源于stack exchange,提问作者DopeBoy
相关产品推荐
相关产品推荐

