display base64 encoded image stored in db

bino

Member
We have images that are being base64 encoded and stored in a clob field in our db. the encoding and storing of the image is working fine. If I run this test to output some of the data to a string I can see there is info stored.

Code:
<script language="speedscript">
def var v-b64-decod-str as longchar no-undo.
def var c                      as char no-undo.
def var v-str-length       as int  no-undo.
 
find record where bla blah ...
 
if avail record then
do:
   copy-lob from img.image-name to v-b64-decod-str.
   assign v-str-length = length(v-b64-decod-str).
   assign codestring = substring(v-b64-decod-str,1,512).
end.
</script>
<head>
<title>test</title>
</head>
<body>
  <textarea id="img" name="img" cols="75" wrap="VIRTUAL" rows="20" >`codestring`</textarea>
  `v-str-length`
</body>
</html>

above code works as long as I hardcode the length of the string.

But what do I do if wanted to output the full string of the base64 code? For example this will return an error. Attempt to exceed maximum size of a CHARACTER variable. (9324). I understand that the string is beyond what a char field can store so how would you output the full value of a longchar value as string?

Code:
<script language="speedscript">
def var v-b64-decod-str as longchar no-undo.
def var c                      as char no-undo.
def var v-str-length       as int  no-undo.
 
find record where bla blah ...
 
if avail record then
do:
   copy-lob from img.image-name to v-b64-decod-str.
   assign v-str-length = length(v-b64-decod-str).
   assign codestring = substring(v-b64-decod-str,1,v-str-length).
end.
</script>
<head>
<title>test</title>
</head>
<body>
  <textarea id="img" name="img" cols="75" wrap="VIRTUAL" rows="20" >`codestring`</textarea>
  `v-str-length`
</body>
</html>

Secondly, if I just wanted to display the image inline this should work but it keeps returning errors.

Code:
<script language="speedscript">
def var v-b64-decod-str as longchar no-undo.
 
find record where blah blah..
 
if avail record then
do:
     copy-lob from img.image-name to v-b64-decod-str.
end.
 
procedure output-header:
  output-content-type ("image/jpg").
  base64-decode (v-b64-decod-str).
end.
 
</script>
 

Cecil

19+ years progress programming and still learning.
What is the purpose of using substring function?


Code:
procedure output-header:
  output-content-type ("image/jpg").
  {&OUT-LONG} base64-decode (v-b64-decod-str).
end.
 

bino

Member
Thanks Cecil,

You cant output the display of a lonchar value to a regular variable if its too long. I was using substring intially to just see if there was some data in the field. So I assigned a regular char var to the subtring value.

Your example will still produce the following error.

Error converting Base64 to RAW (12119).
 

Cecil

19+ years progress programming and still learning.
I've not tested this code, so it might not work first time.

Code:
PROCEDURE output-header:
        
    /* Output the decoded base64 string into the binary format and export to the webstream...*/
    DEFINE VARIABLE mpData          AS MEMPTR   NO-UNDO.
    DEFINE VARIABLE v-b64-decod-str AS LONGCHAR NO-UNDO.
    
    SET-SIZE(mpData)= 0. /* Rule of thumb, always set the size to zero first.*/
    
    ASSIGN
        mpData = BASE64-DECODE (v-b64-decod-str).
    
    /* Optional - I use it for debugging purpose when using firefox/firebug. */
    output-http-header("X-Powered-By", SUBSTITUTE('Progress OpenEdge &1 - &2',
                                                  PROVERSION,
                                                  PROGRAM-NAME(1)).

    output-http-header("Content-Length",STRING(GET-SIZE(mpData))).
    output-content-type ("image/jpg").
    {&OUT-LONG} mpData.
    SET-SIZE(mpData)= 0.

    RETURN.
END.

Code:
<script language="speedscript">
PROCEDURE CodedBase64String:
    
    /* OUTPUT THE Encoded String to the WebStream...*/

    def var v-b64-decod-str as longchar no-undo.
    def var c                      as char no-undo.
    def var v-str-length       as int  no-undo.

    FIND record where bla blah ...
 
    IF AVAILABLE record THEN
    DO:
       COPY-LOB FROM img.image-name TO OBJECT v-b64-decod-str NO-CONVERT NO-ERROR.

       ASSIGN v-str-length = LENGTH(v-b64-decod-str).
       
       IF NOT ERROR-STATUS:ERROR AND v-str-length GT 0 THEN 
       DO:
           {&OUT-LONG} v-b64-decod-str.
       END.
    END.

    RETURN.
END PROCEDURE.
 
</script>
<head>
<title>test</title>
</head>
<body>
  <textarea id="img" name="img" cols="75" wrap="VIRTUAL" rows="20" ><!--WSS RUN CodedBase64String IN THIS-PROCEDURE. --></textarea>
  `v-str-length`
</body>
</html>
 

bino

Member
Cecil that worked. Thank you for your help. Part of what I was missing was
output-http-header("Content-Length",STRING(GET-SIZE(mpData))).

and the {&OUT-LONG} mpData.

Another option that I tried that worked that uses data uri's is shown below. It works great but data uri's dont work with IE7/IE6. I prefer the output header method since it seems to work in all browsers. Thanks again for your help.

Code:
<script language="speedscript">
def var v-image         as memptr   no-undo.
def var c                   as char        no-undo.
def var i                    as int          no-undo.
 
 
  find record where bla blah ...
 
  if avail record then
  do:
      {&out} '<img src="data:image/jpg;base64,'.
      copy-lob from img.image-name to v-image.
 
     do i = 1 to length(img.image-name):
       assign c = get-string(v-image, i, 1).
 
       {&out} c.
 
     end.
 
     {&out} ' width="800px" alt="image">'.
  end.
 
</script>
 

Cecil

19+ years progress programming and still learning.
Not a problem. It gave me a little break from what I was working on a the time.
 
Top