-1

In a servlet I had to read an image file from disk, encode it to Base64 and then send back to the client. Because I only found samples for iOS, Python and some other kinds (principally all do it the same way) I thought I post my code here to help others ;)

CAUTION! This should only work for files up to 2GB: setting capacity of ByteBuffer only takes an int.

Marvin Emil Brach
  • 3,984
  • 1
  • 32
  • 62

2 Answers2

1
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    FileInputStream in = null;
    try {
        File file = new File(getServletContext().getRealPath("/<thePath>/<fileName>"));
        ByteBuffer buff = ByteBuffer.wrap(new byte[(int)image.length() + (image.length() % 1024 > 0 ? 1024 : 0)]);
        byte[] b = new byte[1024]; 
        in = new FileInputStream(file);
        while(in.read(b) != -1) {
            buff.put(b);
        }
        response.getWriter().write(Base64.encode(buff.array()));
    } catch(Exception e) {
        String msg = "Fehler beim lesen des Bildes";
        LOG.log(Level.SEVERE, msg, e);
        response.sendError(500, msg);
        return;
    } finally {
        if(in != null) in.close();
    }
}

CAUTION! This should only work for files up to 2GB: setting capacity of ByteBuffer only takes an int.

Marvin Emil Brach
  • 3,984
  • 1
  • 32
  • 62
  • use `org.apache.commons.codec.binary.Base64InputStream` – user1516873 Oct 24 '12 at 12:53
  • Hey that's a nice package I just didn't know (yeah, shame on me). Thanks for the advice. But in the end I have to get A `String` (code is just a snippet) and pack it with some other data before sending the response, so I don't see actually an additional value for me, just that I got an additional lib. But I think I will use it future projects. – Marvin Emil Brach Oct 24 '12 at 13:32
  • basic idea: don't use byte[] or String to store large amount of data. Java has stream implementations for almost all cases. – user1516873 Oct 24 '12 at 13:40
  • So far so good. It seems I'm too stupid: I don't see how to do it with `Base64InputStream` in another way like I did. And if its just about not loading data in memory I find [Udo Klimaschewski](http://stackoverflow.com/users/1740554/udo-klimaschewski)s answer cleaner and it don't need an additional library. – Marvin Emil Brach Oct 24 '12 at 14:13
  • don't use sun.misc.* classes, it is internal java API and can be changed in future. http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html. And you can use Base64InputStream like this: `Base64InputStream stream = new Base64InputStream(new FileInputStream("path to file")); IOUtils.copy(stream, response.getOutputStream())`;` – user1516873 Oct 24 '12 at 14:59
  • Yes, that I can see. If you will post this as an answer I will accept yours instead. – Marvin Emil Brach Oct 24 '12 at 15:10
1

Why so complicated and why read the complete image into memory? A much simpler solution:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
    enc.encode(new FileInputStream("/path/to/file.whatever"), response.getOutputStream());
}
Udo Klimaschewski
  • 5,150
  • 1
  • 28
  • 41
  • Thanks for the hint, but the code I posted is only a part of the whole action I do serverside. I have to pack the data among other in a greater response. But I will see if I could make a chain for writing directly on OutputStream. But +1 anyway – Marvin Emil Brach Oct 24 '12 at 13:18
  • A fat downvote for the reason mentioned in http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html – BalusC Sep 26 '15 at 09:14