title: why does Java servlet gives ClientAbortException when file size larger than about 2 MB?
body: <p>I'm trying to write a java servlet that is located on a Linux server, that may be used by a client to download a video file. It works when the file size is small (perhaps less than 2 MB), but larger file sizes return the error: <code>org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe</code>. </p>
  
  <p>After searching Google, it appears this error occurs when the client breaks the connection. In my case, I'm using the client and can confirm that I'm not doing anything that would break the connection (at least not on purpose) -- the browser remains open, etc., when this error occurs.</p>
  
  <p>Any idea what might be causing this (and how to fix)?</p>
  
  <pre><code>public class GetFile extends HttpServlet {
  
  @Override
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
  }
  
  protected void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
  
  String filename ="init_java";
  
  try {
  
      // get user parameters
      filename = req.getParameter("fileId");  // complete path to video file
      //res.setContentType("video/mp4");  //not working
      res.setContentType("application/x-download");  
  
      File file=new File(filename);
  
      if (file.exists()) {
  
          res.setHeader("Content-Disposition", "inline; filename=\""+filename+"\"");
          res.setHeader("Cache-Control", "cache, must-revalidate");
          //res.setHeader("Pragma", "public"); // not sure when to use
          returnFile(filename, res.getOutputStream());
  
      } else {
          //error handling goes here
      }     
  
  } catch (Exception e) {
      ...
  } finally {
      ... 
  }
  }
  
  
  private static void returnFile(String filename, OutputStream out) throws FileNotFoundException, IOException {
    InputStream in = null;
    try {
        in = new BufferedInputStream(new FileInputStream(filename));
        byte[] buf = new byte[4 * 1024]; // 4K buffer
        int bytesRead;
        while ((bytesRead = in.read(buf)) != -1) {
            out.write(buf, 0, bytesRead);
        }
  
    } finally {
        if (in != null) in.close();
    }
  }
  
  }
  </code></pre>
  
  <p><strong><em>UPDATE 1</em></strong></p>
  
  <p>I'm seeing the following error in the <code>mod_jk.log</code> file (which transfers the request from Apache web server to GlassFish application server):</p>
  
  <pre class="lang-none prettyprint-override"><code>[info] init_jk::mod_jk.c (3383): mod_jk/1.2.40 initialized
  [error] ajp_connection_tcp_get_message::jk_ajp_common.c (1313): wrong message format 0xcad5 from ::1:8009
  [error] ajp_get_reply::jk_ajp_common.c (2204): (worker1) Tomcat is down or network problems. Part of the response has already been sent to the client
  [info] ajp_service::jk_ajp_common.c (2673): (worker1) sending request to tomcat failed (recoverable), because of protocol error (attempt=1)
  [info] ajp_process_callback::jk_ajp_common.c (2000): Writing to client aborted or client network problems
  [info] ajp_service::jk_ajp_common.c (2673): (worker1) sending request to tomcat failed (unrecoverable), because of client write error (attempt=2)
  [info] jk_handler::mod_jk.c (2799): Aborting connection for worker=worker1
  </code></pre>
  
  <p>It appears to be tracking what I observe, but I'm not an expert here -- does this offer any insight into what might be the root cause?</p>