Write an InputStream to an HttpServletResponse

前端 未结 3 1432
一个人的身影
一个人的身影 2020-12-03 07:02

I have an InputStream that I want written to a HttpServletResponse. There\'s this approach, which takes too long due to the use of byte[]

InputStream is = ge         


        
相关标签:
3条回答
  • 2020-12-03 07:46

    Just write in blocks instead of copying it entirely into Java's memory first. The below basic example writes it in blocks of 10KB. This way you end up with a consistent memory usage of only 10KB instead of the complete content length. Also the enduser will start getting parts of the content much sooner.

    response.setContentLength(getContentLength());
    byte[] buffer = new byte[10240];
    
    try (
        InputStream input = getInputStream();
        OutputStream output = response.getOutputStream();
    ) {
        for (int length = 0; (length = input.read(buffer)) > 0;) {
            output.write(buffer, 0, length);
        }
    }
    

    As creme de la creme with regard to performance, you could use NIO Channels and a directly allocated ByteBuffer. Create the following utility/helper method in some custom utility class, e.g. Utils:

    public static long stream(InputStream input, OutputStream output) throws IOException {
        try (
            ReadableByteChannel inputChannel = Channels.newChannel(input);
            WritableByteChannel outputChannel = Channels.newChannel(output);
        ) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(10240);
            long size = 0;
    
            while (inputChannel.read(buffer) != -1) {
                buffer.flip();
                size += outputChannel.write(buffer);
                buffer.clear();
            }
    
            return size;
        }
    }
    

    Which you then use as below:

    response.setContentLength(getContentLength());
    Utils.stream(getInputStream(), response.getOutputStream());
    
    0 讨论(0)
  • 2020-12-03 07:49
    BufferedInputStream in = null;
    BufferedOutputStream out = null;
    OutputStream os;
    os = new BufferedOutputStream(response.getOutputStream());
    in = new BufferedInputStream(new FileInputStream(file));
    out = new BufferedOutputStream(os);
    byte[] buffer = new byte[1024 * 8];
    int j = -1;
    while ((j = in.read(buffer)) != -1) {
        out.write(buffer, 0, j);
    }
    
    0 讨论(0)
  • 2020-12-03 07:57

    I think that is very close to the best way, but I would suggest the following change. Use a fixed size buffer(Say 20K) and then do the read/write in a loop.

    For the loop do something like

    byte[] buffer=new byte[20*1024];
    outputStream=response.getOutputStream();
    while(true) {
      int readSize=is.read(buffer);
      if(readSize==-1)
        break;
      outputStream.write(buffer,0,readSize);
    }
    

    ps: Your program will not always work as is, because read don't always fill up the entire array you give it.

    0 讨论(0)
提交回复
热议问题