0

I have the following method:

 /**
  * Encodes the byte array into base64 string
  * @param imageByteArray - byte array
  * @return String a {@link java.lang.String}
  */
public static String encodeImage(byte[] imageByteArray) {
    return Base64.encodeBase64URLSafeString(imageByteArray);
}

I am importing "org.apache.commons.codec.binary.Base64;" However, I get the error:

Multiple markers at this line - The method encodeBase64URLSafeString(byte[]) is undefined for the type Base64 - Line breakpoint:MySQLConnection [line: 287] - encodeImage(byte[])

I have copied this code from "http://www.myjeeva.com/2012/07/how-to-convert-image-to-string-and-string-to-image-in-java/". I am using Eclipse Juno (fully updated) and GWT.

Does anyone know what I am doing wrong here?

Regards,

Glyn

Thank you Markus A. I have now created this Class from your information:

package org.AwardTracker.server;

public class Base64Decode {
private final static String base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

public static byte[] decode(String s) {

    // remove/ignore any characters not in the base64 characters list
    // or the pad character -- particularly newlines
    s = s.replaceAll("[^" + base64chars + "=]", "");

    // replace any incoming padding with a zero pad (the 'A' character is
    // zero)
    String p = (s.charAt(s.length() - 1) == '=' ? (s.charAt(s.length() - 2) == '=' ? "AA"
            : "A")
            : "");

    s = s.substring(0, s.length() - p.length()) + p;
    int resLength = (int) Math.ceil(((float) (s.length()) / 4f) * 3f);
    byte[] bufIn = new byte[resLength];
    int bufIn_i = 0;

    // increment over the length of this encrypted string, four characters
    // at a time
    for (int c = 0; c < s.length(); c += 4) {

        // each of these four characters represents a 6-bit index in the
        // base64 characters list which, when concatenated, will give the
        // 24-bit number for the original 3 characters
        int n = (base64chars.indexOf(s.charAt(c)) << 18)
                + (base64chars.indexOf(s.charAt(c + 1)) << 12)
                + (base64chars.indexOf(s.charAt(c + 2)) << 6)
                + base64chars.indexOf(s.charAt(c + 3));

        // split the 24-bit number into the original three 8-bit (ASCII)
        // characters

        char c1 = (char) ((n >>> 16) & 0xFF);
        char c2 = (char) ((n >>>8) & 0xFF);
        char c3 = (char) (n & 0xFF);

        bufIn[bufIn_i++] = (byte) c1;
        bufIn[bufIn_i++] = (byte) c2;
        bufIn[bufIn_i++] = (byte) c3;

    }

    return bufIn;
}


}

And changed the call to: import org.AwardTracker.server.Base64Decode;

public static String encodeImage(byte[] imageByteArray) {
    return Base64Decode(imageByteArray); [Error on this line]
}

And I now get the error:

Multiple markers at this line - The method Base64Decode(byte[]) is undefined for the type MySQLConnection

Help greatfuly appreciated.

Regards,

Glyn

Round Three

OK, so I had my encrypt and decrypt arround the wrong way. This has now been corrected and placed in the correct libraries. However I still have an error in the encodeImage method. This is the method I use to call the encodeImage method. I suspect that the lines:

java.sql.Blob imageBlob = result.getBlob(1);
byte[] imageData = imageBlob.getBytes(1, (int) imageBlob.length());

are not correct. However, I have defined ImageData as a byte[] so I do not see why encodeImage thinks it is a String?

public String getImageData(String id){
    ResultSet result = null;
    PreparedStatement ps = null;
    String imageDataString = null;
    try {
        // Read in the image from the database.
        ps = conn.prepareStatement(
              "SELECT at_cub_details.cd_photograph " +
                      "FROM at_cub_details " + 
                      "WHERE at_cub_details.cd_id = \"" + id + "\"");
        result = ps.executeQuery();
        while (result.next()) {
            java.sql.Blob imageBlob = result.getBlob(1);
            byte[] imageData = imageBlob.getBytes(1, (int) imageBlob.length());

            //Convert Image byte array into Base64 String
            imageDataString = encodeImage(imageData);
        }

    }

Resulting in an error in:

public static String encodeImage(byte[] imageByteArray) {
    return Base64Encode.encode(imageByteArray); [Error on this line]
}

of "The method encode(String) in the type Base64Encode is not applicable for the arguments (byte[])"

Thanks for all your help.

Regards,

Glyn

p.s., I think this will deserve a blog when I am finished as I can not find any definitve work in this area and I would have thought that this would be used very often. My next project.

The Encode class is:

package org.AwardTracker.server;

public class Base64Encode {
private final static String base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

public static String encode(String s) {

    // the result/encoded string, the padding string, and the pad count
    String r = "", p = "";
    int c = s.length() % 3;

    // add a right zero pad to make this string a multiple of 3 characters
    if (c > 0) {
        for (; c < 3; c++) {
            p += "=";
            s += "\0";
        }
    }

    // increment over the length of the string, three characters at a time
    for (c = 0; c < s.length(); c += 3) {

        // we add newlines after every 76 output characters, according to
        // the MIME specs
        if (c > 0 && (c / 3 * 4) % 76 == 0)
            r += "\r\n";

        // these three 8-bit (ASCII) characters become one 24-bit number
        int n = (s.charAt(c) << 16) + (s.charAt(c + 1) << 8)
                + (s.charAt(c + 2));

        // this 24-bit number gets separated into four 6-bit numbers
        int n1 = (n >> 18) & 63, n2 = (n >> 12) & 63, n3 = (n >> 6) & 63, n4 = n & 63;

        // those four 6-bit numbers are used as indices into the base64
        // character list
        r += "" + base64chars.charAt(n1) + base64chars.charAt(n2)
                + base64chars.charAt(n3) + base64chars.charAt(n4);
    }

    return r.substring(0, r.length() - p.length()) + p;
}
}

And the Decode class is:

package org.AwardTracker.server;

public class Base64Decode {
private final static String base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

public static byte[] decode(String s) {

    // remove/ignore any characters not in the base64 characters list
    // or the pad character -- particularly newlines
    s = s.replaceAll("[^" + base64chars + "=]", "");

    // replace any incoming padding with a zero pad (the 'A' character is
    // zero)
    String p = (s.charAt(s.length() - 1) == '=' ? (s.charAt(s.length() - 2) == '=' ? "AA"
            : "A")
            : "");

    s = s.substring(0, s.length() - p.length()) + p;
    int resLength = (int) Math.ceil(((float) (s.length()) / 4f) * 3f);
    byte[] bufIn = new byte[resLength];
    int bufIn_i = 0;

    // increment over the length of this encrypted string, four characters
    // at a time
    for (int c = 0; c < s.length(); c += 4) {

        // each of these four characters represents a 6-bit index in the
        // base64 characters list which, when concatenated, will give the
        // 24-bit number for the original 3 characters
        int n = (base64chars.indexOf(s.charAt(c)) << 18)
                + (base64chars.indexOf(s.charAt(c + 1)) << 12)
                + (base64chars.indexOf(s.charAt(c + 2)) << 6)
                + base64chars.indexOf(s.charAt(c + 3));

        // split the 24-bit number into the original three 8-bit (ASCII)
        // characters

        char c1 = (char) ((n >>> 16) & 0xFF);
        char c2 = (char) ((n >>>8) & 0xFF);
        char c3 = (char) (n & 0xFF);

        bufIn[bufIn_i++] = (byte) c1;
        bufIn[bufIn_i++] = (byte) c2;
        bufIn[bufIn_i++] = (byte) c3;

    }

    return bufIn;
}


}

I have finally found an encode class that works:

package org.AwardTracker.server;

public class Base64Encode2 {
 private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

    private static int[]  toInt   = new int[128];

    static {
        for(int i=0; i< ALPHABET.length; i++){
            toInt[ALPHABET[i]]= i;
        }
    }

/**
 * Translates the specified byte array into Base64 string.
 *
 * @param buf the byte array (not null)
 * @return the translated Base64 string (not null)
 */
public static String encode(byte[] buf){
    int size = buf.length;
    char[] ar = new char[((size + 2) / 3) * 4];
    int a = 0;
    int i=0;
    while(i < size){
        byte b0 = buf[i++];
        byte b1 = (i < size) ? buf[i++] : 0;
        byte b2 = (i < size) ? buf[i++] : 0;

        int mask = 0x3F;
        ar[a++] = ALPHABET[(b0 >> 2) & mask];
        ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
        ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
        ar[a++] = ALPHABET[b2 & mask];
    }
    switch(size % 3){
        case 1: ar[--a]  = '=';
        case 2: ar[--a]  = '=';
    }
    return new String(ar);
}

}

Thanks for all your help Markus A. It is greatly appreciated.

Regards,

Glyn

Glyn
  • 1,933
  • 5
  • 37
  • 60
  • do you have teh correct version of Base64 as the methods have changed around a few times. Make sure the version you have has the call yo are using. – Sean F Feb 11 '13 at 03:19
  • You encode a byte array (which is an image?) using URL encoder??? – SwiftMango Feb 11 '13 at 03:19

1 Answers1

1

GWT does not provide the apache commons package, so I don't think you'll be able to just use this function in your code.

Here are the things you can use in GWT:

https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation

If you do want to use it, you need to actually have the source code of the Base64 class (and all its dependencies) available and put that into your project somewhere where the GWT compiler can reach it to turn it into JavaScript.

For other ways to do the encoding, see here:

How do I encode/decode short strings as Base64 using GWT?

Addition for new question added to original post:

For starters, you need to call static functions on a class like this:

return Base64Decode.decode(imageByteArray);

But you also seem to have your types backwards: encodeImage takes a byte[] and returns a String, while Base64Decode.decode takes a String and returns a byte[]. You probably need to be using the equivalent Base64Encode.encode function instead of the decode function.

Community
  • 1
  • 1
Markus A.
  • 12,349
  • 8
  • 52
  • 116
  • Thanks Markus A. I have taken the code from your links. However I still get an error. I have updated the posting with the new code. Thanks Glyn. – Glyn Feb 11 '13 at 04:47
  • Hi Markus, you are absolutely right on the mark here and I have corrected this on both sides (i.e., swapping my decodes and encodes). A silly mistake resulting from my frustration with this. So my classes are all correct now and are in the correct place. However, I still have an issue with an error on the line calling the encode class. Please see above. Thanks, Glyn. – Glyn Feb 11 '13 at 22:25
  • @user1965599 I'm not really seeing any changes to your post. Have you saved them already? If you are talking about this version, I had added a reply to that to my answer already (see under **Addition for new question...**). Let me know if you update your post one more time and need more help. – Markus A. Feb 11 '13 at 22:36
  • @user1965599 Ah! There's your update. Well... the error is telling you that `Base64Encode.encode` is defined as `public encode(String data)` not `public encode(byte[] data)` (you're passing it the wrong type of input data). Unfortunately you didn't post the definition of your encode method, so I can't say anything more at this point. But there's probably still an issue in that piece of code. (Just to make sure: You didn't just rename decode to encode, right? That won't work...) – Markus A. Feb 11 '13 at 23:11
  • Hi Markus A, I have posted both the encode and decode code definitions. Am I going about this the right way? Should I be decoding on the Server side and then encoding on the Client side instead? Thanks for your help, Glyn. – Glyn Feb 12 '13 at 01:22
  • Hi Markus A., I have found another encode class that works and have posted it above. Now all I have to do is display it (the next battle)! Thanks for all your help. Regards, Glyn. – Glyn Feb 12 '13 at 03:47