2

I am working with a REST service that returns a blob of images as part of Multipart/mixed data. There can be 1 or more images in the content. The boundary for this blob is returned in the Content-Type. If the boundary of this multipart content is, for ex: b4081556-a000-48d9-a4e5-xyz345, the response looks something like this: --boundary Content-Type: image/jpeg BLOB1 --boundary Content-Type: image/jpeg BLOB2 --boundary Content-Type: image/jpeg BLOB3 --boundary--

I need to parse this response into individual image files(blobs) and display them on the front end. I am doing this on ColdFusion and have tried everything with no luck. For simplicity's sake, I wanted to first use a simple blob with one image. Then eliminate the encapsulation boundaries from it and read the content into a variable, but I keep getting this error:

ColdFusion was unable to create an image from the specified source file. Ensure that the file is a valid image file.

Screen shot of error message Here's what I tried to extract the encapsulation boundary:

<cfset thumbnail_filecontent = currPageThumnail_raw_resp.fileContent.toByteArray()>
<cfset thumbnail_str = toString(thumbnail_filecontent)>

<!---remove the encapsulation boundary--->
<cfset content1 = removeChars(thumbnail_str, 1, 64)> 
<cfset content2 = Left(content1, Len(content1)-43)>

<!---Convert the string into binary--->
<cfset image_content = toBinary(toBase64(content2))>

<cfimage action="INFO" source="#image_content#" structname="objImageInfo" />
<cfdump var="#objImageInfo#"><cfabort>

I tried to use ImageNew() also but ended up with the same error. I am not sure if I am missing something. I am starting to wonder if extracting the encapsulation boundary from the response and then working with the file content is the right(and only?) way to do it?

If that is the only way, then is it a good idea to convert the bytearray into string, extract the image content and then convert it back to binary to process it? Is there a better way?

This is my first time working with Multipart data and any help would be greatly appreciated! Thanks in advance.

Response screen shot:

Screen shot of response

SOS
  • 6,430
  • 2
  • 11
  • 29
  • Just did, thanks:) – justanotherprogrammer Sep 23 '19 at 20:05
  • Edit: *"...the response looks something like this.."* Could you post a screen shot of the response? There may be a better way to parse it than diy. – SOS Sep 23 '19 at 20:34
  • 1
    Try using something like this to parse the response for you. Loop through the # of parts to extract each image. This thread saves the content to a file, but you could probably do it in memory too. https://stackoverflow.com/questions/43594950/how-to-read-multipart-response-in-coldfusion – SOS Sep 23 '19 at 22:14
  • I remember looking at that thread before, but I havent tried it because I wanted to see if there was something natively available in coldfusion (without having to resort to Java objects), given its rich library to work with images. Having said that, I will try that now and keep you posted. Thanks so much for quick response:) – justanotherprogrammer Sep 24 '19 at 15:40
  • You're welcome. Using java objects isn't that far off from what CF uses internally for handling http requests, emails, etc... AFAIK, CF doesn't expose the low level aspect of parsing through any tags or functions. – SOS Sep 24 '19 at 16:07
  • 1
    Btw, I'm not sure if you need to know the boundary value up front, like that thread implies. Depending on the response format, you might be able to get away with creating the ByteArrayDataSource from binary and use "multipart/mixed" (no boundary) for content the type – SOS Sep 24 '19 at 17:26
  • You are correct! It didnt need the boundary value in my case. This solution worked like a charm! For whatever reason, none of the image functions or the file read/write functionality with coldfusion worked for me. I will post the code snippet soon. Thanks so much! – justanotherprogrammer Sep 24 '19 at 17:53
  • *"...none of the image functions or ...worked for me"* Do you mean didn't work with the original code? I'm not surprised. Parsing is delicate. Converting the binary into a string and back again likely corrupted something. – SOS Sep 24 '19 at 19:51
  • That is my guess too. Converting between binary and string might have screwed up the data. Plus, stripping the encapsulation boundary from the blob may have stripped off its essential bytes, so using any of the ColdFusion Image functionality (even though they supported byte arrays) ever worked! – justanotherprogrammer Sep 25 '19 at 13:12
  • 1
    Yep. Not every task needs java, but in cases like this it's the right tool for the job since it has all of the format and parsing rules already figured out. Glad you got it working! – SOS Sep 25 '19 at 14:27

1 Answers1

2

Thanks @Ageax for your help with this. I very much appreciate it!

My solution is not very different from this. The only difference being- mine involves images/thumbnails and as pointed out it doesn't need the boundary embedded with Content-Type.

<cfscript>
            var path = GetDirectoryFromPath(GetCurrentTemplatePath());
            destination = path & "\thumbnails\";
            contentType = "multipart/mixed";
            byteArrayDS = createObject("java", "javax.mail.util.ByteArrayDataSource").init(thumbnail_filecontent, contentType);
            mimeMP = createObject("java", "javax.mail.internet.MimeMultipart").init(byteArrayDS);

            // loop through parts
            for (i = 0; i < mimeMP.getCount(); i++) {
                writeOutput("<br>Processing part["& i &"]");
                bodyPart = mimeMP.getBodyPart( javacast("int", i)); 

                // **** NOTE: Update directory path ****
                if (!isNull(bodyPart)) {
                    outputFile = createObject("java", "java.io.File").init(destination &"thumbnail"& i &".png");
                    bodyPart.saveFile(outputFile);
                    writeOutput("<br>Saved: "& outputFile.getAbsolutePath());
                }
            } 
        </cfscript>
  • 1
    Also, if you're receiving a mix of image types, you can use methods like `bodyPart.isMimeType("type/subtype")` to determine the appropriate file extension. – SOS Sep 24 '19 at 20:41
  • 1
    That is a helpful tip. I believe the response returns both jpg and png. Thanks again:) – justanotherprogrammer Sep 24 '19 at 21:20