Home > Back-end >  FileOutputStream sends 0 byte file
FileOutputStream sends 0 byte file

Time:09-16

I am trying to allow a user to download a file (attachment) using Java to serve up the download. I have been partially successful. The file is read, and on the client side there is a prompt for a download. A file is saved successfully, but it has 0 bytes. Here is my server side code:

String stored = "/var/lib/tomcat/webapps/myapp/attachments/"   request.getParameter("stored");
String realname = request.getParameter("realname");

// Open the input and output streams
FileInputStream attachmentFis = new FileInputStream(stored);
FileOutputStream attachmentFos = new FileOutputStream(realname);

try {
    // Send the file
    byte[] attachmentBuffer = new byte[1024];
    int count = 0;
    while((count = attachmentFis.read(attachmentBuffer)) != -1) {
        attachmentFos.write(attachmentBuffer, 0, count);
    }
} catch (IOException e) {
    // Exception handling
} finally {
    // Close the streams
    attachmentFos.flush();
    attachmentFos.close();
    attachmentFis.close();
}

For context, this is in a servlet. The files have an obfuscated name, which is passed as "stored" here. The actual file name, the name the user will see, is "realname".

What do I need to do to get the actual file to arrive at the client end?

EDIT Following suggestions in the comments, I changed the write to include the 0, count parameters and put the close stuff in a finally block. However, I am still getting a 0 byte file when I attempt a download.

CodePudding user response:

As others have observed, you'd be better off using try-with-resources & let that handle the closing.

Assuming you have some Logging Framework available, maybe the following would cast light on the matter...

try {
    LOG.info ("Requesting....");

    final String                   stored   = "/var/lib/tomcat/webapps/myapp/attachments/"   request.getParameter("stored");
    LOG.info ("stored.......: {}", stored);

    final String                   realname = request.getParameter("realname");
    LOG.info ("realname.....: {}", realname);

    final File fileStored   = new File(stored);
    LOG.info ("fileStored...: {}", fileStored  .getCanonicalPath());

    final File fileRealname = new File(realname);
    LOG.info ("fileRealname.: {}", fileRealname.getCanonicalPath());

    try(final InputStream  attachmentFis = new FileInputStream (fileStored);
        final OutputStream attachmentFos = new FileOutputStream(fileRealname))
    {
        final byte[] attachmentBuffer = new byte[64 * 1024];

        int    count;
        while((count = attachmentFis.read (attachmentBuffer)) != -1) {
            ;          attachmentFos.write(attachmentBuffer, 0, count);

            LOG.info ("Written......: {} bytes to {}", count, realname);
        }
        attachmentFos.flush(); // Probably done automatically in .close()
    }
    LOG.info ("Done.");
}
catch (final Exception e) {
    LOG.error("Problem!.....: {}", request, e);
}

CodePudding user response:

If it won't reach the finally block, you should stop ignoring the IOException which is being thrown:

catch (IOException e) {

    // Exception handling
    System.err.println(e.getMessage());
}

I'd asssume that the realname is just missing an absolute path.

  • Related