title: java.lang.OutOfMemoryError: Java heap space during bytea download
body: <p>I'm using this code to download bytea object from PostgreSQL:</p>
  
  <pre><code>public void initFileDBData() throws SQLException, IOException
  {
      if (ds == null)
      {
          throw new SQLException("Can't get data source");
      }
      Connection conn = ds.getConnection();
  
      if (conn == null)
      {
          throw new SQLException("Can't get database connection");
      }
  
      PreparedStatement ps = null;
  
      try
      {
          conn.setAutoCommit(false);
          ps = conn.prepareStatement("SELECT * FROM PROCEDURE_FILES WHERE ID = ?");
  
          ps.setInt(1, id);
          ResultSet rs = ps.executeQuery();
          while (rs.next())
          {
              String file_name = rs.getString("FILE_NAME");
              InputStream binaryStreasm = rs.getBinaryStream("FILE");
              FacesContext fc = FacesContext.getCurrentInstance();
              ExternalContext ec = fc.getExternalContext();
  
              ec.responseReset();
              ec.setResponseContentLength(binaryStreasm.available());
              ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + file_name + "\"");
  
              byte[] buf;
  
                  buf = new byte[binaryStreasm.available()];
                  int offset = 0;
                  int numRead = 0;
                  while ((offset &lt; buf.length) &amp;&amp; ((numRead = binaryStreasm.read(buf, offset, buf.length - offset)) &gt;= 0))
                  {
                      offset += numRead;
                  }
  
              HttpServletResponse response
                  = (HttpServletResponse) FacesContext.getCurrentInstance()
                  .getExternalContext().getResponse();
  
              response.setContentType("application/octet-stream");
              response.setHeader("Content-Disposition", "attachment;filename=" + file_name);
              response.getOutputStream().write(buf);
              response.getOutputStream().flush();
              response.getOutputStream().close();
              FacesContext.getCurrentInstance().responseComplete();
          }
  
      }
      finally
      {
          if (ps != null)
          {
              ps.close();
          }
          conn.close();
      }
  }
  </code></pre>
  
  <p>But when I start to download the code I get java.lang.OutOfMemoryError: Java heap space on this line:</p>
  
  <pre><code> buf = new byte[binaryStreasm.available()];
  </code></pre>
  
  <p>Can I somehow optimize the code to consume less memory?</p>
  
  <p>Updated code:</p>
  
  <pre><code>public void initFileDBData() throws SQLException, IOException
      {
          if (ds == null)
          {
              throw new SQLException("Can't get data source");
          }
          Connection conn = ds.getConnection();
  
          if (conn == null)
          {
              throw new SQLException("Can't get database connection");
          }
  
          PreparedStatement ps = null;
  
          try
          {
              conn.setAutoCommit(false);
              ps = conn.prepareStatement("SELECT *, octet_length(FILE) as file_length FROM PROCEDURE_FILES WHERE ID = ?");
  
              ps.setInt(1, id);
              ResultSet rs = ps.executeQuery();
              while (rs.next())
              {
                  String file_name = rs.getString("FILE_NAME");
                  FacesContext fc = FacesContext.getCurrentInstance();
                  ExternalContext ec = fc.getExternalContext();
  
                  ec.responseReset();
                  ec.setResponseContentLength(rs.getInt("file_length"));
                  ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + file_name + "\"");
  
                  HttpServletResponse response
                      = (HttpServletResponse) FacesContext.getCurrentInstance()
                      .getExternalContext().getResponse();
  
                  byte[] buffer = new byte[4096];
  
                  try (InputStream input = rs.getBinaryStream("FILE");
                      OutputStream output = response.getOutputStream())
                  {
                      int numRead = 0;
  
                      while ((numRead = input.read(buffer)) != -1)
                      {
                          output.write(buffer, 0, numRead);
                      }
                  }
  
                  response.setContentType("application/octet-stream");
                  response.setHeader("Content-Disposition", "attachment;filename=" + file_name);
                  response.getOutputStream().write(buffer);
                  response.getOutputStream().flush();
                  response.getOutputStream().close();
                  FacesContext.getCurrentInstance().responseComplete();
              }
          }
          finally
          {
              if (ps != null)
              {
                  ps.close();
              }
              conn.close();
          }
      }
  </code></pre>