Search code examples
arrayscoldfusionblobmultipartcfimage

How to parse Multipart/mixed data in Coldfusion


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


Solution

  • 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>