Decode base64 image in apigee

@Dino: We are facing issue while decoding base64 string? We tested below and didn't result as expected.

Please suggest.

https://github.com/DinoChiesa/ApigeeEdge-Java-Simple-Base64

Thanks.

Solved Solved
0 8 1,915
1 ACCEPTED SOLUTION

Hi Vinay

I added an example of decoding a Base64 payload into the github repo.

When I added the sample I discovered that the result of the decoding was not being properly set, outside of the tests! So I had to update the callout to do it properly.

Sorry for the inconvenience.

This should work properly for you now.

With the updates, you need to update your policy files to reference v1.0.3 of the callout jar.

Also please add the commons-codec jar into your proxies as a dependency.

Good luck.

View solution in original post

8 REPLIES 8

hi

you said your results are not expected. Translation: "It didn't work."

But can you give me more information? What exactly are you doing?

More information is better . Show me the way you are using this Java policy, and how you got the image data in the first place.

Help ME to help YOU.

decode.png

we are passing base64 encoded string to java callout but after the below code the

if(isBase64) always returns false

<em>InputStream is = newBase64InputStream(content, false, lineLength, linebreak);</em>

We were able to get the decode to return the byte array using the below change, but the output that gets displayed in Apigee-Edge for b64_result has only few characters even though the length is 500+ characters.

wanted to check if below code is decoding correct ?

our need is to to decode and post as a multi part to backend.

<strong></strong><em>publicExecutionResult execute(finalMessageContext msgCtxt,
                               finalExecutionContext execContext) {
    try {
        Base64Action action = getAction(msgCtxt);
        InputStream content = msgCtxt.getMessage().getContentAsStream();
        intlineLength = getLineLength(msgCtxt, -1);
        InputStream is = newBase64InputStream(content, (action == Base64Action.Encode), lineLength, linebreak);
        byte[] bytes = IOUtils.toByteArray(is);
        booleanisBase64 = org.apache.commons.codec.binary.Base64.isBase64(bytes);
        if (isBase64 && action == Base64Action.Encode) {
            msgCtxt.setVariable(varName("action"), action.name().toLowerCase());
            booleanwantStringDefault = (action == Base64Action.Encode);
            booleanwantString = getStringOutput(msgCtxt, wantStringDefault);
            if (wantString) {
                msgCtxt.setVariable(varName("wantString"), wantString);
                String encoded = StringUtils.newStringUtf8(bytes);
                msgCtxt.setVariable(varName("result"), encoded);
            }
            returnExecutionResult.SUCCESS;
        } else if (action == Base64Action.Decode) {
            msgCtxt.setVariable(varName("action"), action.name().toLowerCase());
            String mimeType = getMimeType(msgCtxt);
            if (mimeType != null) {
                msgCtxt.setVariable(varName("mimeType"), mimeType);
            }
            msgCtxt.setVariable(varName("input_result"), msgCtxt.getMessage().getContent());
            msgCtxt.setVariable(varName("result"), bytes);
            msgCtxt.setVariable(varName("bytesLength"), bytes.length);
            returnExecutionResult.SUCCESS;
        } else {
            msgCtxt.setVariable(varName("error"), "not Base64");
            returnExecutionResult.ABORT;
        }
    } catch (Exception e) {
        //System.out.println(ExceptionUtils.getStackTrace(e));String error = e.toString();
        msgCtxt.setVariable(varName("exception"), error);
        intch = error.lastIndexOf(':');
        if (ch >= 0) {
            msgCtxt.setVariable(varName("error"), error.substring(ch + 2).trim());
        } else {
            msgCtxt.setVariable(varName("error"), error);
        }
        msgCtxt.setVariable(varName("stacktrace"), ExceptionUtils.getStackTrace(e));
        returnExecutionResult.ABORT;
    }
}<br></em>

Hi Vinay

ok, I understand you are running the same code from the Java callout. But it didn't work as you expected.

My observations:

  • isBase64 holds the result value of a utility method that checks if the data is base64 encoded. This method is well tested and proven. We can trust the result.
  • A value of false is telling you that the input data is not base64 encoded. We can be pretty sure that this is not a "false negative". If isBase64 is false, the input data is really really not base64-encoded.

You are thinking that you have provided the input to this java callout in the correct way, but in fact that is not so. The input to the Java callout is not a base64 stream. It is not being provided in the correct way.

Without any evidence to the contrary, I suppose that there is nothing incorrect in the behavior of the Base64 callout. The tests run correctly.

Therefore I suspect the problem is in your usage of the callout. To diagnose that, I have some questions.

  • How do you make the client request? Can you share the curl command you use? or a client script that sends out an HTTP request?
  • Are you sure the input is base64 encoded upon input? The client would need to explicitly do the encoding. Has your client done that? If so, how? what language are you using to do the base64 encoding, and can you show me the code that does it?
  • Can you show me just the bare base64-encoded image data, before it gets embedded into the HTTP request on the client side?
  • What is the content type of the HTTP request? What does the payload look like?
  • In the API Proxy, How do you extract the base64 data from the inbound request?


How do you make the client request? Can you share the curl command you use? or a client script that sends out an HTTP request?
>>client request is via postman

curl -X POST \
https://test.apigee.com/v1/testdecode \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: text/plain' \
-H 'Postman-Token: 8c29f4b0-3133-1676-b561-a427d8e02526' \
-d <<base64 string>>
Are you sure the input is base64 encoded upon input? The client would need to explicitly do the encoding. Has your client done that? If so, how? what language are you using to do the base64 encoding, and can you show me the code that does it?
>>If we use the same code(jar) to encode and try decoding it doesn't function.
Can you show me just the bare base64-encoded image data, before it gets embedded into the HTTP request on the client side?
>>
What is the content type of the HTTP request? What does the payload look like?
>>text/plain & base 64 encoded.(attached the curl with sample encoded)
In the API Proxy, How do you extract the base64 data from the inbound request?
>>Its in request.content which is passed to callout..

we are just passing b64_action as decode & b64_mimeType as image/png to the callout.


Can you please show a sample encode/decode working & the parameters passed to java callout?

curl.txt

@Dino

Still not able to work it out :(..Can you check if it is working at your end.just submit sample attachment to encode and decode. Appriciate your help.

@Dino: Is there a way to reach out to you to discuss on above issue?

Hi Vinay

I added an example of decoding a Base64 payload into the github repo.

When I added the sample I discovered that the result of the decoding was not being properly set, outside of the tests! So I had to update the callout to do it properly.

Sorry for the inconvenience.

This should work properly for you now.

With the updates, you need to update your policy files to reference v1.0.3 of the callout jar.

Also please add the commons-codec jar into your proxies as a dependency.

Good luck.

Thanks. It actually converts now and show the decode bytes.Will open new request as how to assign & post the multipart request.