13 Replies Latest reply on Jun 15, 2011 6:37 PM by -==cfSearching==-

    Byte Array Base64 Binary

    zeejayy Level 1

      I'm currently working on code to consume a soap webservice in cf8. I have most of the

      implementation working and am able to use several of the methods defined in this

      particular WS without issue. I'm having a problem with a particular function that

      sends a PDF document to the WS. In the WS docs it lists the document 'content'

      field as needing to be base64binary and from talking to the developers they say it

      specifficly needs to be a byte array of base64binary.

       

      Here's a snippet of the coldfusion code I'm using:

       

      <cffile action="readbinary" file="#arguments.filepath#" variable="documentBinaryData"/>
      
      <cfsavecontent variable="soapBody">
      <cfoutput>
      <?xml version="1.0" encoding="utf-8"?>
      <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Body>
          <AddDocument xmlns="http://idoccentral.com">
            <IKey>#arguments.iKey#</IKey>
            <documentDetail>
              <Source>#arguments.source#</Source>
              <FolderID>#arguments.folderID#</FolderID>
              <DocumentID>0</DocumentID>
              <DisplayName>#arguments.displayName#</DisplayName>
              <DocumentDescriptionID>0</DocumentDescriptionID>
              <DocumentDescription>#arguments.documentDescription#</DocumentDescription>
              <FileType>#arguments.fileType#</FileType>
              <Content>#BinaryEncode(documentBinaryData,"Base64")#</Content>
            </documentDetail>
          </AddDocument>
        </soap:Body>
      </soap:Envelope>
      </cfoutput>
      </cfsavecontent>
      
      <cfhttp url="http://stage.doccentral.trpoint.com/DCWebService/IDCService.asmx" method="post" result="httpResponse" timeout="600" throwonerror="yes">
           <cfhttpparam type="header" name="SOAPAction" value="http://idoccentral.com/AddDocument"/>
           <cfhttpparam type="header" name="accept-encoding" value="no-compression"/>
           <cfhttpparam type="xml" value="#trim(soapBody)#"/>
      </cfhttp>
      

       

       

      The WS response is telling me that everything was ok, I can see the file on the

      remote system but when i try to view it from there i get a corrupt file as if my encoding

      is incorrect or they are not decoding it correctly.

       

      I've used this same method before for a different web service that also recieves

      base64binary encoded PDF documents and it's working just fine there.

       

      As far as i can tell im encoding it to base64Binary correctly, not sure about the

      byte array part but im assuming thats whet the cffile readbinary is returning.

       

      Am i doing something wrong in my code or is it more likely to be something on

      their end or something wrong in my header?

        • 1. Re: Byte Array Base64 Binary
          -==cfSearching==- Level 4

          ...the developers they say it specifficly needs to

          be a byte array of base64binary.

           

          Something about that description feels "off". But if you mean an array of bytes converted to a base64 string, nothing about your code jumps out at me as being glaringly wrong.

           

          The WS response is telling me that everything was ok,

           

          Does the content-length line match up with your request size?

          when i try to view it from there i get a corrupt file

           

          How are you accessing the file, directly or with another web service call? Could the problem be with the code used to view/retrieve the file?

           

          Message was edited by: -==cfSearching==-

          1 person found this helpful
          • 2. Re: Byte Array Base64 Binary
            zeejayy Level 1

            This is for an MLS Realtor service. It allows them to put their documents up so their clients can access them easily.

            I have a development account on the staging server that i can log into and download the files. Seems to be just a simple http file download.

             

            I'll have to check the content length thats something i haven't really had to look at before.

            I've done a couple of web service projects in CF but im still learning some of the ins and outs.

            • 3. Re: Byte Array Base64 Binary
              -==cfSearching==- Level 4

              log into and download the files that i have sent in. Seems

              to be just a simple http file download.

               

              Oh, I thought it might be something more complex.  I still do not see anything obviously wrong with the code. Unless the definition of byte array base64binary is different than what we are thinking it is ..

               

              Did you check the basics like file size? How does the final file compare to the original - smaller, larger, same .. ? Also, I assume the issue occurs with every file, not just certain types, etcetera... ?

              1 person found this helpful
              • 4. Re: Byte Array Base64 Binary
                zeejayy Level 1

                Yeah I'm not doing anything fancy with the WS, just basically authenticating

                and then calling the addDocument method to send the PDF content.

                 

                Their system only accepts PDF format, the file type param is useless, so i haven't

                tried any other file types. I have tried it with multiple different PDF files just to make

                sure it wasn't a broken or non standard file coming from my end.

                 

                I just did a compare on file size and the original file was 123k, resulting file on

                their server when i download it is only 545 bytes so yeah it's completly fubar at

                that point. You would think even with an improper encode or decode that the

                result file would be a lot bigger then that.

                 

                Do you think maybe i need to pass a content length in my header? The reason

                I'm doing the whole cfsavecontent cfhttp method is because i tried it as a cfInvoke

                on the webservice and couldn't manage to get it working by simply building out a

                struct to pass in and letting CF handle all the XML internaly, it would always come

                back and tell me that it couldn't find a method called addDocument with those

                params. The cfinvoke webservice is however working ok for the other WS method

                i need to call in order to get my auth key.

                 

                I'm beginning to think the problem lies on their end, it's been very difficult and slow

                going to get ahold of somebody over there to help me though. The main point of this

                posting was to find out if my encoding method was wrong, from what i can tell theres

                not really another way to do that encoding in CF though.

                • 5. Re: Byte Array Base64 Binary
                  -==cfSearching==- Level 4
                  it is only 545 bytes

                   

                  Hmm... are the resulting files always that small? Crazy thought, but open the tiny file with notepad or something. Just to see if even looks like a truncated pdf. They usually start with %PDF-(version number).

                   

                  Also you might sniff the traffic to see what your full soap request looks like. See how it compares to their sample

                  http://stage.doccentral.trpoint.com/DCWebService/IDCService.asmx?op=AddDocument

                   

                   

                  The main point of this posting was to find out if my encoding method was wrong

                   

                  Unless I am misunderstanding what is meant by base64binary.. I do not think so. Your code looks correct to me.

                   

                   

                  The reason I'm doing the whole cfsavecontent cfhttp method is because i tried it as a cfInvoke on the webservice and couldn't manage to get it working by simply building out a struct to pass in and letting CF handle all the XML internaly, it would always come back and tell me that it couldn't find a method called addDocument with those params.

                   

                  Out of curiosity, what did you try? It does not look too complicated (famous last words I know ...)

                  • 6. Re: Byte Array Base64 Binary
                    -==cfSearching==- Level 4

                    Ah.. I see it is lunch time for the jive forums!

                     

                    -Leigh

                    • 7. Re: Byte Array Base64 Binary
                      zeejayy Level 1

                      I did look at the file contents for the corrupted pdf and it looked like complete garbage.

                      there was no PDF at the start like I see when I look at the orignal file.

                       

                      The other way that i had tried invoking the WS was like this.

                       

                      <cffile action="readbinary" file="c:\somefile.pdf" variable="documentBinaryData"/>
                      
                      <cfset args.IKey="my ikey from previous WS call">
                      <cfset args.documentDetail.Source="My Website">
                      
                      <cfset documentDetail=structNew()>
                      <cfset documentDetail.FolderID="1234">
                      <cfset documentDetail.DocumentID="0 for a new document">
                      <cfset documentDetail.DisplayName="Document Name">
                      <cfset documentDetail.DocumentDescriptionID="0 for a new description">
                      <cfset documentDetail.DocumentDescription="Document Description">
                      <cfset documentDetail.FileType="pdf">
                      <cfset documentDetail.Content=BinaryEncode(documentBinaryData,"Base64")>
                      
                      <cfinvoke 
                      webservice="http://stage.doccentral.trpoint.com/DCWebService/IDCService.asmx?wsdl"  
                      method="addDocument" 
                      returnvariable="dcSvc">
                      
                           <cfinvokeargument name="IKey" value="#getIkey.iKey#">
                           <cfinvokeargument name="documentDetail" value="#documentDetail#">
                      
                      </cfinvoke>
                      

                       

                      This results in a CF error "Web service operation addDocument with parameters

                      (bunch of long params that all look correct) cannot be found". It's odd because im using

                      this method successfully for one of the other function calls to create a folder and it's using

                      a structure for the folder data which is very close to the document detail struct

                       

                      I'm going to do some extended tracing today and I'm, hopefully, going to hear from the devs

                      so i can get this straightened out. Thanks for you suggestions, I think you've helped me

                      answer my basic questions.

                      • 8. Re: Byte Array Base64 Binary
                        -==cfSearching==- Level 4

                        This results in a CF error "Web service operation addDocument with parameters (bunch of long params that all look correct) cannot be found". It's odd because im using this method successfully for one of the other function calls

                         

                        Weird. I pulled down the wsdl locally and at first I got the same " ... cannot be found" error with CF9. I was curious if the "Content" parameter was the source of the problem, so I removed it from the "Document" definition and refreshed the  wsdl.

                         

                              <s:element minOccurs="0" maxOccurs="1" name="Content" type="s:base64Binary"/>

                         

                        As I expected, the cfinvoke call started working after that. Do not ask me why, but now even a direct call to http://stage.doccentral.trpoint.com/DCWebService/IDCService.asmx?wsdl seems to work. Even after I deleted the stubs and restarted CF.  Obviously I cannot run a real test without a key. But the "..cannot be found" error went away and I do get a valid xml response. Weird...

                        • 9. Re: Byte Array Base64 Binary
                          zeejayy Level 1

                          Well I finaly got the cfinvoke method to work as well. still not getting a vaild file though.

                          The code below should handle base64 encoding of the documentBinaryData from a

                          binary byte array automaticly based on the WSDL. Also isn't base64 encoding pretty

                          standard as an XML safe way of passing binary data?

                           

                          <cffile action="readbinary" file="c:\somefile.pdf" variable="documentBinaryData"/>

                          <cfset documentDetail=structNew()>
                          <cfset documentDetail.Source="Source Application Name">
                          <cfset documentDetail.FolderID="1234">
                          <cfset documentDetail.DocumentID="0 for a new document">
                          <cfset documentDetail.DisplayName="Document Name">
                          <cfset documentDetail.DocumentDescriptionID="0 for a new description">
                          <cfset documentDetail.DocumentDescription="Document Description">
                          <cfset documentDetail.FileType="pdf">
                          <cfset documentDetail.Content=documentBinaryData>

                          <cfinvoke
                          webservice="http://stage.doccentral.trpoint.com/DCWebService/IDCService.asmx?wsdl" 
                          method="addDocument"
                          returnvariable="dcSvc">
                               <cfinvokeargument name="IKey" value="My Ikey">
                               <cfinvokeargument name="documentDetail" value="#documentDetail#">
                          </cfinvoke>

                           

                          Here a snip of what i got back as a response after i sent them a SOAP trace.

                           

                          "I had our developer look at the soap trace and test the xml, he pointed out that

                          looking at the trace, it seems like the document is encoded to base64 format but

                          is sent as a string and not as a byte array."

                           

                          I did a bunch of testing and research again today and from what i can tell the readbinary

                          action is returning a byte array so i donno what the heck the developer is smoking

                          or why their WS won't accept my encoding correctly.

                          • 10. Re: Byte Array Base64 Binary
                            zeejayy Level 1

                            OK we can put this to rest. I finally got it to work. Apparently they needed the base 64

                            encoded string to be further encoded into sequence of bytes. so basically all i needed to

                            do was use the java getBytes method on my string and then pass that in as the content.

                             

                            Thanks again for your help trying to figure this out.

                            • 11. Re: Byte Array Base64 Binary
                              -==cfSearching==- Level 4

                              i donno what they heck

                              the developer is smoking

                               

                              At the risk of sounding like I am smoking something, could they possibly mean they want you to base64 encode it and then convert it back into binary and send that?

                              • 12. Re: Byte Array Base64 Binary
                                zeejayy Level 1

                                Actualy that is pretty much what it was. goes binary file data to base 64 encoded string

                                then getBytes on that string which returns some sort of binary data it looked like.

                                • 13. Re: Byte Array Base64 Binary
                                  -==cfSearching==- Level 4

                                  Actualy thats is pretty much what it was.

                                   

                                  Yep. I responded before I saw your last post. But good to have it confirmed. base64binary .. guess we should have been more literal ;-)

                                   

                                  then getBytes on that string which returns some sort of binary data

                                  Yes, it should return binary just like your cffile read. As far as getBytes(), since there is a CF function for that already, I would use it instead. Granted either should work with the correct encoding.

                                   

                                  Anyway, I am glad you finally got it working!