38

I know this has probably been asked 10000 times, however, I can't seem to find a straight answer to the question.

I have a LOB stored in my db that represents an image; I am getting that image from the DB and I would like to show it on a web page via the HTML IMG tag. This isn't my preferred solution, but it's a stop-gap implementation until I can find a better solution.

I'm trying to convert the byte[] to Base64 using the Apache Commons Codec in the following way:

String base64String = Base64.encodeBase64String({my byte[]});

Then, I am trying to show my image on my page like this:

<img src="data:image/jpg;base64,{base64String from above}"/>

It's displaying the browser's default "I cannot find this image", image.

Does anyone have any ideas?

Thanks.

Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193
El Guapo
  • 5,581
  • 7
  • 54
  • 82
  • can you post the full code...i need it for reference...i also have the same problem...but i dont have any idea of how the code will be.. – Lucky Jan 15 '13 at 13:33

5 Answers5

43

I used this and it worked fine (contrary to the accepted answer, which uses a format not recommended for this scenario):

StringBuilder sb = new StringBuilder();
sb.append("data:image/png;base64,");
sb.append(StringUtils.newStringUtf8(Base64.encodeBase64(imageByteArray, false)));
contourChart = sb.toString();
WhyNotHugo
  • 9,423
  • 6
  • 62
  • 70
13

According to the official documentation Base64.encodeBase64URLSafeString(byte[] binaryData) should be what you're looking for.

Also mime type for JPG is image/jpeg.

Crozin
  • 43,890
  • 13
  • 88
  • 135
  • 1
    The [PNG example on the Wikipedia article](https://secure.wikimedia.org/wikipedia/en/wiki/Data_URI_scheme#Examples) suggests that using + and / is okay. – Daniel Trebbien Jan 29 '11 at 18:07
  • 1
    Has anyone actually tried using the output of Base64.encodeBase64URLSafeString() to see if it works in a browser? encodeBase64URLSafeString() does not appear to generate valid/standard base64 encoding. To make a base64-encoded string URI-compliant, you should apply standard URI character escaping to it. I don't think the above function is what you want. – Keeth Aug 14 '13 at 17:28
  • This answer did not actually generate the proper string for me. The answer from Hugo contains the missing encoding to make it work. – ryber Dec 12 '13 at 22:30
3

That's the correct syntax. It might be that your web browser does not support the data URI scheme. See Which browsers support data URIs and since which version?

Also, the JPEG MIME type is image/jpeg.

Community
  • 1
  • 1
Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193
2

You may also want to consider streaming the images out to the browser rather than encoding them on the page itself.

Here's an example of streaming an image contained in a file out to the browser via a servlet, which could easily be adopted to stream the contents of your BLOB, rather than a file:

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
  {
    ServletOutputStream sos = resp.getOutputStream();
    try {
      final String someImageName = req.getParameter(someKey);

      // encode the image path and write the resulting path to the response
      File imgFile = new File(someImageName);

      writeResponse(resp, sos, imgFile);
    }
    catch (URISyntaxException e) {
      throw new ServletException(e);
    }
    finally {
      sos.close();
    }
  }

  private void writeResponse(HttpServletResponse resp, OutputStream out, File file)
    throws URISyntaxException, FileNotFoundException, IOException
  {
    // Get the MIME type of the file
    String mimeType = getServletContext().getMimeType(file.getAbsolutePath());
    if (mimeType == null) {
      log.warn("Could not get MIME type of file: " + file.getAbsolutePath());
      resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    }

    resp.setContentType(mimeType);
    resp.setContentLength((int)file.length());

    writeToFile(out, file);
  }

  private void writeToFile(OutputStream out, File file)
    throws FileNotFoundException, IOException
  {
    final int BUF_SIZE = 8192;

    // write the contents of the file to the output stream
    FileInputStream in = new FileInputStream(file);
    try {
      byte[] buf = new byte[BUF_SIZE];
      for (int count = 0; (count = in.read(buf)) >= 0;) {
        out.write(buf, 0, count);
      }
    }
    finally {
      in.close();
    }
  }
jhouse
  • 2,674
  • 1
  • 18
  • 17
  • I'm using Spring Web MVC and the whole page is being built using tiles, etc... I really don't want to go through the PITA of creating another controller and calling each image separately, but thanks! – El Guapo Jan 30 '11 at 01:16
1

If you don't want to stream from a servlet, then save the file to a directory in the webroot and then create the src pointing to that location. That way the web server does the work of serving the file. If you are feeling particularly clever, you can check for an existing file by timestamp/inode/crc32 and only write it out if it has changed in the DB which can give you a performance boost. This file method also will automatically support ETag and if-modified-since headers so that the browser can cache the file properly.

Mark Porter
  • 1,650
  • 9
  • 9