从URL读取InputStream并写入HttpServletResponse而不创建临时文件

时间:2016-09-06 13:16:26

标签: java

我尝试从URL读取一个InputStream并直接写入HttpServletResponse而不在HttpServlet中创建临时文件,但未能获得该文件的实际Content-Length。我被告知我无法在不读取数据的情况下确定流中的数据量。有人能帮我吗?我真的很感激。

3 个答案:

答案 0 :(得分:1)

由于您正在阅读网址,因此您应该从该网址的<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> 标题中获取该长度。

Content-length

请注意,您应使用HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.connect(); if ( connection.getResponseCode() == 200 ) { int contentLength = connection.getContentLength(); response.setContentLength( contentLength ); inputStream.available()方法只告诉您可以在不阻塞的情况下读取多少字节(即等待下一个块从网络到达)。它没有告诉你流的大小!但是在available()中,您可以使用HttpURLConnection方法获取内容长度标头的值。

一旦这样做,您就可以开始读写循环来复制所有数据,例如

getContentLength()

请记住在所有这些中使用try-catch,因为在这样的事务中可能会抛出多种异常。当您发现异常时,请记住在响应中设置响应代码,即 200。

答案 1 :(得分:0)

在数据耗尽之前,没有理由无法从请求对象中读取输入流 - 将其缓冲到内存中。事实上,根据我的经验,这总是如何完成的;我可以指望一只手的手指我看到输入流写入文件而不是缓冲到内存中的次数。如果你得到一个内容长度标题,你可以用它作为起点,但我不会依赖它。你需要防止过多的输入,因为你不知道输入流的远端是什么,所以他们服务器你正在联系你可能会发送很多材料,你用尽RAM来处理它

继续调用read()直到得到-1。其他读取方法也可用于此,但您将添加更多逻辑来检测文件结束。

答案 2 :(得分:-1)

我使用这段代码,没有进行内容长度管理(IOUtils在commons-io中并且不创建临时文件)但是适用于小文件和大文件:

public static void downloadFile(HttpServletResponse response, InputStream inputStream, String fileName,
        String contentType) throws IOException {

    response.reset();
    response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"",
            fileName));

    if (contentType != null) {
        response.setHeader("Content-Type", contentType);
    }

    OutputStream output = response.getOutputStream();

    IOUtils.copy(inputStream, output);

    output.flush();
    output.close();
}