Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Is it possible to make this string an image?
Message
From
17/07/2017 13:22:57
 
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Environment versions
Visual FoxPro:
VFP 9 SP2
OS:
Windows 10
Database:
MS SQL Server
Miscellaneous
Thread ID:
01652660
Message ID:
01652690
Views:
92
This message has been marked as a message which has helped to the initial question of the thread.
>>>Hi everybody,
>>>
>>>If I got this as a value, what is it and can this be transformed into an image somehow?
>>>
>>>
>>>ÿØÿà
>>
>>I have seen this when a Memo field containing binary Image value got read into XML using CursorToXML without the proper formatting.
>
>I've checked our methods and they are as following (not using CursorToXML and I don't think we either had troubles with them before):
>
>
>PROTECTED PROCEDURE xml_dbf2str
>      LPARAMETERS tcTable, tnNumRecs, tcNoHeader
>      LOCAL lcTableName, lcDTD, laFieldInfo, lnFieldCount, lni
>      LOCAL lcData, lcCRLF, llNoHeader, lcRetVal
>
>      THIS.write_log('Entering method...', PROGRAM(), '1')
>
>      IF VARTYPE(tcTable)<>'C'
>         lcRetVal='100-Parameters Error: Table Name C8, #Records (optional, -1 = all)'
>         THIS.write_log('Returning: '+lcRetVal, PROGRAM(), '2')
>         RETURN lcRetVal
>      ENDIF
>      IF PCOUNT()<3
>         llNoHeader=.T.
>         IF PCOUNT()<2                  &&default is to fill resulting object with data
>            tnNumRecs=1
>         ENDIF
>      ELSE
>         llNoHeader=INLIST(UPPER(tcNoHeader),'T','Y')
>      ENDIF
>
>      SELECT (tcTable)                  &&make sure you're on the right table
>      IF !UPPER(ALIAS())==UPPER(ALLTRIM(tcTable))
>         lcRetVal='202- Table Not Open - '+tcTable
>         THIS.write_log('Returning: '+lcRetVal, PROGRAM(), '2')
>         RETURN lcRetVal
>      ENDIF
>      IF tnNumRecs<0                  &&want entire table?
>         tnNumRecs=RECCOUNT()
>         GO TOP
>      ENDIF
>      lcCRLF=CRLF
>      lcTableName=ALIAS()+'_Table'
>      &&put field info into array for creating DTD and each record
>      DIMENSION laFieldInfo[1]
>      lnFieldCount=AFIELDS(laFieldInfo)
>
>      &&can be sent as a parameter or turned on globally via .ini setting
>      IF llNoHeader AND !this.lXMLDTD
>         lcDTD=''
>      ELSE
>         &&standard DTD (Document Type Definition) for tables converted to xml
>         lcDTD='<?xml version="1.0" encoding="ISO-8859-1"?>'+lcCRLF+lcCRLF+;
>            '<!DOCTYPE '+lcTableName+' ['+lcCRLF+;
>            '  <!ELEMENT '+lcTableName+' (Record+)>'+lcCRLF+;
>            '  <!ATTLIST '+lcTableName+lcCRLF+;
>            '    RecCount i4 #REQUIRED>'+lcCRLF+;
>            '  <!ELEMENT Record (#PCDATA)>'+lcCRLF+;
>            '  <!ATTLIST Record'+lcCRLF
>         &&add field list to DTD (Document Type Definition)
>         FOR lni=1 TO lnFieldCount
>            lcFoxType=laFieldInfo[lnI,2]
>            DO CASE
>               CASE lcFoxType = "C"
>                  lcType = "string"
>               CASE lcFoxType = "M"
>                  lcType = "bin.hex"
>               CASE lcFoxType $ "NFY"
>                  lcType = "number"
>               CASE lcFoxType = "L"
>                  lcType = "boolean"
>               CASE lcFoxType = "O"
>                  lcType = "object"
>               CASE lcFoxType = "I"
>                  lcType = "i4"
>               CASE lcFoxType = "D"
>                  lcType = "date.iso8601"
>               CASE lcFoxType = "T"
>                  lcType = "datetime.iso8601"
>               OTHERWISE
>                  lcType = lcFoxType
>            ENDCASE
>
>            lcDTD=lcDTD+;
>               '    name='+     PADR(laFieldInfo[lnI,1],10)+;
>               '    type='+     PADR(lcType,16)+;
>               '    size='+     PADR(TRANSFORM(laFieldInfo[lnI,3]),5)+;
>               '    precision='+PADR(TRANSFORM(laFieldInfo[lnI,4]),5)+;
>               '    #REQUIRED'+lcCRLF
>         ENDFOR
>         lcDTD=lcDTD+'>'+lcCRLF+']>'+lcCRLF+lcCRLF
>      ENDIF
>
>      &&standard table into starts this way
>      lcData='<XML>'+lcCRLF+;
>         '  <'+lcTableName+'>'+lcCRLF+;
>         '    <RecCount>'+TRANSFORM(MIN(tnNumRecs,RECCOUNT()))+'</RecCount>'+lcCRLF
>      IF tnNumRecs > 0
>         scan next tnNumRecs
>            lcData = lcData + lcCRLF + '    <Record>' + lcCRLF
>            for lni = 1 TO lnFieldCount
>               if laFieldInfo[lnI,2] = 'G'
>                  && do nothing - can't process
>               else
>                  lFieldValue = evaluate(laFieldInfo[lnI,1])
>                  do case
>                     case laFieldInfo[lnI, 2] $ 'CM'                  && character, memo
>                          lcStr = rtrim(nvl(lFieldValue, ''))
>                     case laFieldInfo[lnI, 2] $ 'NFB'                 && numeric, float, double
>                          lcStr = alltrim(str(nvl(lFieldValue, 0), 20, 5))
>                     case laFieldInfo[lnI, 2] = 'I'                   && integer
>                          lcStr = transform(nvl(lFieldValue, 0))
>                     case laFieldInfo[lnI, 2] = 'Y'                   && currency
>                          lcStr = alltrim(str(mton(nvl(lFieldValue, ntom(0))), 20, 4))
>                     case laFieldInfo[lnI, 2] = 'D'                   && date
>                          lcStr = dtoc(nvl(lFieldValue, {}))
>                     case laFieldInfo[lnI, 2] = 'T'                   && date/time
>                          lcStr = ttoc(nvl(lFieldValue, {}))
>                     case laFieldInfo[lnI, 2] = 'L'                   && logical
>                          lcStr = iif(nvl(lFieldValue, .f.),'.T.', '.F.')
>                     case laFieldInfo[lnI, 2] $ 'QW'                  && Blob/VarBinary
>                          lcStr = nvl(lFieldValue, '')
>                     otherwise
>                          lcStr = ''
>                  endcase
>                  lcData = lcData + '      <' + laFieldInfo[lnI, 1] + '>' + ;
>                           lcStr  +      '</' + laFieldInfo[lnI, 1] + '>' + lcCRLF
>               endif
>            endfor
>            lcData = lcData+'    </Record>' + lcCRLF
>         endscan
>      endif
>
>      lcData = lcData+'  </'+lcTableName+'>'+lcCRLF+ '</XML>'+lcCRLF
>      this.write_log('Returning: '+lcDTD+lcData, program(), '2')
>      return lcDTD+lcData
>      endproc
>
>   protected procedure xm2_dbf2str
>      lparameters tcTable, tnNumRecs
>      local lcTableName, lcDTD, laFieldInfo, lnFieldCount, lni, lnF, lnR, lcF, lcR
>      local lcData, llNoHeader, lcRetVal, lnPlaces
>
>      this.write_log('Entering method...', program(), '1')
>
>      if vartype(tcTable)<>'C'
>         lcRetVal='100-Parameters Error: Table Name C8, #Records (optional, -1 = all)'
>         this.write_log('Returning: ' + lcRetVal, program(), '2')
>         return lcRetVal
>      endif
>      if vartype(tnNumRecs) <> 'N'         && default is to fill resulting object with data
>         tnNumRecs = 1
>      endif
>
>      select (tcTable)                     && make sure you're on the right table
>      if !upper(alias()) == upper(alltrim(tcTable))
>         lcRetVal = '202- Table Not Open - ' + tcTable
>         this.write_log('Returning: ' + lcRetVal, program(), '2')
>         return lcRetVal
>      endif
>      if tnNumRecs < 0                     && want entire table?
>         tnNumRecs = reccount()
>         go top
>      endif
>      
>      lcTableName = alias() + '_Table'
>      && put field info into array for creating DTD and each record
>      dimension laFieldInfo[1]
>      lnFieldCount = afields(laFieldInfo)
>
>      && standard table into starts this way
>      lcData = '<XM2><' + lcTableName + '><Fields>'
>      lnF    = 0
>      for lni = 1 TO lnFieldCount
>          if laFieldInfo[lnI, 2] <> 'G'
>             lnF    = lnF + 1
>             lcF    = transform(lnF)
>             lcData = lcData + '<' + lcF + '>' + laFieldInfo[lnI,1] + '</' + lcF + '>'
>         endif
>      endfor
>      lcData = lcData + '</Fields>'
>      if tnNumRecs > 0
>         lnR = 0
>         scan next tnNumRecs
>            lnR    = lnR + 1
>            lcR    = transform(lnR)
>            lcData = lcData + '<R' + lcR + '>'
>            lnF    = 0
>            for lni = 1 to lnFieldCount
>               if laFieldInfo[lnI, 2] = 'G'
>                  && can't process - skip
>               else
>                  lnF = lnF + 1
>                  if !empty(nvl(evaluate(laFieldInfo[lnI, 1]), ''))
>                     lFieldValue = evaluate(laFieldInfo[lnI, 1])
>                     * This.write_log('Working on field ' + transform(lnI) + ': ' + laFieldInfo[lnI, 1] + ;
>                     *              ", type: " + laFieldInfo[lnI, 2], program(), '5')
>                     do case
>                        case laFieldInfo[lnI, 2] $ 'CM'                  && character, memo
>                             lcStr = rtrim(lFieldValue)
>                        case laFieldInfo[lnI, 2] $ 'NFB'                 && numeric, float, double
>                             lnPlaces = iif(lFieldValue % 1 = 0, 0, 5)
>                             lcStr = alltrim(str(lFieldValue, 20, lnPlaces))
>                        case laFieldInfo[lnI, 2] = 'I'                   && integer
>                             lcStr = transform(lFieldValue)
>                        case laFieldInfo[lnI, 2] = 'Y'                   && currency
>                             lcStr = alltrim(str(mton(lFieldValue), 20, 4))
>                        case laFieldInfo[lnI, 2] = 'D'                   && date
>                             lcStr = dtoc(lFieldValue)
>                        case laFieldInfo[lnI, 2] = 'T'                   && date/time
>                             lcStr = ttoc(lFieldValue)
>                        case laFieldInfo[lnI, 2] = 'L'                   && logical
>                             lcStr = iif(lFieldValue,'.T.', '.F.')
>                        case laFieldInfo[lnI, 2] $ 'QW'                  && Blob/VarBinary
>                             lcStr = lFieldValue
>                        otherwise
>                             lcStr = ""
>                     endcase
>                     if len(lcStr) > 0
>                        lcF = transform(lnF)
>                        lcData = lcData + '<' + lcF + ;
>                                 iif(.lXM2IncludeLength, ' L=' + transform(len(lcStr)), '') + ;
>                                 '>' + lcStr + '</' + lcF + '>'
>                     endif
>                  endif
>               endif
>            endfor
>            lcData = lcData+'</R' + lcR + '>'
>         endscan
>      endif
>
>      lcData = lcData + '</' + lcTableName + '></XM2>'
>      this.write_log('Returning: ' + lcData, program(), '2')
>      return lcData
>      endproc
>
I believe this is exactly the problem I was facing, because it tries to interpret the binary value from the memo field, and that will produce this short piece of character codes:
CREATE CURSOR cutest (image M)
APPEND BLANK
REPLACE image WITH FILETOSTR(GETFILE("JPG"))
MESSAGEBOX(image)
lcString = rtrim(nvl(Image, ''))
MESSAGEBOX(lcstring)
If you compare that with the output of CursorToXML it looks like this:
CURSORTOXML("cuTest","test.xml",1,8+512)
and the image part is inside a ![CDATA[ block in the xml file.
Christian Isberner
Software Consultant
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform