› Clovertech Forums › Cloverleaf › Issue converting base64 file images to PDF
I have been asked to use tcl to do web service call to a CDR database and retrieve the documents/images and then convert them into PDF. My issue is I can retrieve the documents just fine but am having an issue converting to PDF. It looks like when I am trying to create the file it is using the actual base64 as the file name. I feel like this is something simple I am missing but most of my work has been with HL7 not document formatting or converting. Here is the section of the code where I am trying to grab the base64 and decode it.
##—————————————————–
## Create the Document
##—————————————————–
regsub -all {\\.br\\} $document “\n” document
regsub -all {\\.nf\\} $document {} document
regsub -all {\\.fi\\} $document {} document
set OBXSegGroup {}
# for dislpaying in the log:
set OBXSegGroupPrint {}
foreach line [split $document \n] {
set OBXSeg $line
set OBXSegGroup [cconcat $OBXSegGroup $OBXSeg \r]
# For displaying in the log
set OBXSegGroupPrint [cconcat $OBXSegGroupPrint $OBXSeg ” “]
}
# Create the output file.
set filemsg $line
exec /hci/bin/b64.o -d $document filemsg
puts $output_fh $filemsg
close $output_fh
}
if {![string equal $errorInformation “”]} {
puts “Error Info: $errorInformation”
}
}
}
Thank you for any help or advice you might have.
-Peter
It would be nice to see what you are dealing with here. However, if I can assume you have what you want after the exec then you need to write the file as binary. Since I cannot see where you opened the file, you may be doing that.
Really, not enough info to provide much help.
Here is the entire code I am using, and it is the exec that I am having an issue with. When I thought they wanted just the base64 document I didn’t have the exec, only had
# Create the output file.
set filemsg $document
puts $output_fh $filemsg
close $output_fh
Here is the full code below:
proc tpsBooneCDRQryPDF {args} {
global HciSite HciSiteDir HciConnName ibdir
keylget args MODE mode ;# Fetch mode
keylget args ARGS pattern ;# get the pattern for the file name
set dispList {} ;# Nothing to return
switch -exact — $mode {
start {
puts “Start Mode : tpsBooneCDRQryPDF”
return { }
}
run {
keylget args MSGID mh ;# get the message handle
set fileList [msgget $mh]
lappend dispList “KILL $mh”
foreach file $fileList {
set inputFile “$ibdir/$file”
set timestamp [clock format [clock seconds] -format %Y%m%d%H%M%S]
puts “Opening input file read only………”
set previousEID 0
set inputFh [open $inputFile r]
fconfigure $inputFh -buffering line
set recordCount 0
puts “Starting processing of input file…..”
while { [gets $inputFh msg] >= 0 } {
set msg [string trim $msg]
set upi [lindex [split $msg “|”] 0]
set repositoryId [lindex [split $msg “|”] 1]
set type [lindex [split $msg “|”] 2]
set key [lindex [split $msg “|”] 3]
set fac [lindex [split $msg “|”] 4]
set mrn [lindex [split $msg “|”] 5]
set vistnum [lindex [split $msg “|”] 6]
set sex [lindex [split $msg “|”] 10]
set dob [lindex [split $msg “|”] 11]
set filename [lindex [split $msg “|”] 12]
set doctype [lindex [split $msg “|”] 16]
set creationdate [lindex [split $msg “|”] 17]
set activitydate [lindex [split $msg “|”] 18]
set visitdate [lindex [split $msg “|”] 20]
set controlIDbase $key
incr recordCount
puts “…. logging for UPI $upi repositoryID: rec count: $recordCount – $repositoryId key: $key starts here ……..Inbound record is : $msg”
set timestamp [clock format [clock seconds] -format %Y%m%d%H%M%S]
#set outputfilename “scimage.output.$key.$recordCount.$timestamp.txt”
set outputfilename “$key.$visitdate.$type”
set outputDir “/hci/quovadx/cis6.1/integrator/testbl/iig/files/booneLoad/outputPDF”
# set outputDir “/data/xfer/ftp/sitebl/boone/test”
set outputFile “$outputDir/$outputfilename”
catch {exec rm -f $outputFile} catch_return
if {[catch {set output_fh [open $outputFile {WRONLY CREAT}]} err]} {
puts ” Failure to open $outputFile for write”
puts ” Error is $err”
return
}
set errorfilename “BooneCDR.error.$recordCount.$timestamp.txt”
set errorDir “/hci/quovadx/cis6.1/integrator/testbl/iig/files/booneLoad/error”
set errorFile “$errorDir/$errorfilename”
catch {exec rm -f $errorFile} catch_return
if {[catch {set error_fh [open $errorFile {WRONLY CREAT}]} err]} {
puts ” Failure to open $errorFile for write”
puts ” Error is $err”
return
}
set errorcnt 0
set errorfound 0
# using a holdMRN in case Soarian is not found on old results. We will use this variable later.
set holdMRN “”
set holdMRNlength [string length $holdMRN]
set date1 [clock format [clock seconds] -format %Y%m%d]
set time1 [clock format [clock seconds] -format %H%M%S]
# fill upi with leading zeros to 24 positions
set zeroMask “000000000000000000000000”
set upi [string range [cconcat $zeroMask $upi] end-23 end]
set upiDisplay [string trimleft $upi 0]
set fatalErrorMsg {}
set retryctr 0
package require TclCurl
######## PatientSearchService query #############################################################################################
#puts “—————————————————————————–”
puts ” — begin query # 1 getPatientsDemographicsBySummary for upi $upiDisplay –”
#puts ” ”
# set up first web service call xml to retreive the patient demographics for this UPI
set soapEnv “<?xml version=’1.0′ encoding=’UTF-8′?>”
append soapEnv “<soapenv:Envelope ”
append soapEnv “xmlns:soapenv=\”http://schemas.xmlsoap.org/soap/envelope/\” xmlns:urn=\”urn:xmltypes.clinical.bjc.org\”>”
append soapEnv “<soapenv:Header/>”
append soapEnv “<soapenv:Body>”
append soapEnv “<urn:getPatientsDemographicsBySummary>”
append soapEnv “<urn:UPI>$upi</urn:UPI>”
append soapEnv “</urn:getPatientsDemographicsBySummary>”
append soapEnv “</soapenv:Body>”
append soapEnv “</soapenv:Envelope>”
set soapEnv [string trim $soapEnv]
puts “SOAP REQUEST : $soapEnv”
if {[file exists “/hci/bin/monitor/productionserver”]} {
set WSserver “https://clinws.carenet.org/gfwsprod2/PatientSearchService”
} else {
set WSserver “https://clinwstest.carenet.org/gfwstest/PatientSearchService”
set WSserver “https://clinwstest.carenet.org/gfwsuser2/PatientSearchService”
set WSserver “https://clinws.carenet.org/gfwsprod2/PatientSearchService”
}
##————————————————————————
## Setup and make call to the ClinDesk Web Services Server
## This call should return patient demo data which will be saved in
## a list variable to be used later
##————————————————————————
set httpHeaders “”
set httpBody “”
set response “”
lappend httpHeaders “Content-Type: text/xml; charset=utf-8”
# issue web service call to get document keys list
set datea [clock format [clock seconds] -format %Y%m%d]
set timea [clock format [clock seconds] -format %H%M%S]
set gooddemoread 0
set lastname “”
set firstname “”
set middlename “”
set sex “”
set dob “”
catch { curl::transfer -url $WSserver \
-httpheader $httpHeaders \
-postfields $soapEnv \
-timeout 20 \
-verbose 0 \
-ipresolve v4 \
-sslverifypeer 0 \
-bodyvar httpBody } response
set dateb [clock format [clock seconds] -format %Y%m%d]
set timeb [clock format [clock seconds] -format %H%M%S]
set time_diff [expr [clock scan “$dateb $timeb”] – [clock scan “$datea $timea”]]
puts “[whereAmI] Elapsed Time – Patient Demo fetch: $time_diff”
##————————————————————————
## Check curl response for error if none check http body for error.
## If none echo error and exit.
##————————————————————————
#puts “**** WEBSERVICE getPatientsDemographicsBySummary RESPONSE : HTTP: $httpBody”
puts “**** WEBSERVICE getPatientsDemographicsBySummary RESPONSE : SOAP: $response”
set errorInformation {}
if { $response == 7 } {
puts “ERROR: Could not connect to Web Services for Demographics read. Server may be down.”
set fatalErrorMsg “Could not connect to Web Services during Demographics read. Server may be down.”
} else {
if { $response == 28 } {
puts “ERROR: Connection to server timeout during Demographics read.”
set fatalErrorMsg “Connection to server timeout during Demographics read.”
} else {
if { $response != 0} {
##————————————————————
## curl error code can be found here:
## http://curl.haxx.se/libcurl/c/libcurl-errors.html
##————————————————————
puts “ERROR: An unidentified error occured error code: $response”
set fatalErrorMsg “An unidentified error occured error code during Demographics read: $response”
} else {
set errorInformation {}
##————————————————————
## Checks for errors with the web server. Puts error to the
## log file.
##————————————————————
##
## Even if the response was 0, there could be an error.
## If the returned httpBody does not begin with the soap envelope tag,
## there was an error, attempt to get the text of the error from <title>.
if {[cequal [string first “<S:Envelope” $httpBody] -1]} {
set response 101
set errorInformation {}
lappend errorInformation {Error condition not read}
lappend errorInformation {Error message text not read}
if {![cequal [string first “<title>” $httpBody] -1]} {
set t1 [string first “<title>” $httpBody]
set t2 [string first “</title>” $httpBody]
incr t1 7
incr t2 -1
set text [string range $httpBody $t1 $t2]
set errorInformation [lreplace $errorInformation 0 0 “$text”]
}
if {![cequal [string first “<p>” $httpBody] -1]} {
set p1 [string first “<p>” $httpBody]
set p2 [string first “</p>” $httpBody]
incr p1 3
incr p2 -1
set text [string range $httpBody $p1 $p2]
set errorInformation [lreplace $errorInformation 1 1 “$text”]
}
puts “[lindex $errorInformation 0] : [lindex $errorInformation 1]”
} else {
# If we made it to here – assuming it was a good response
# First pull out the xml from the soap body so we can use GRM on the xml to
# read the data.
set index1 [string first “<S:Body” $httpBody]
set index2 [string first “</S:Body>” $httpBody]
set xmlmsg [string range $httpBody [expr $index1 +8] [expr $index2 – 1] ]
if {[string first “<patientName>” $xmlmsg] < 0} {
puts “NO PATIENT DEMO DATA RETURNED – no need to go further”
set fatalErrorMsg ” NO PATIENT DEMO DATA RETURNED for Demographics read.”
set datHandleList [datlist]
foreach handle $datHandleList {
datdestroy $handle
}
set grmHandleList [grmlist]
foreach handle $grmHandleList {
grmdestroy $handle
}
#return
} else {
set gooddemoread 1
}
if {$gooddemoread} {
# create a temporary message handle for grmfetch
set tmpmh [msgcreate data]
msgset $tmpmh $xmlmsg
# read/fetch in the data into the cloverleaf xml format
set ghIn [grmcreate -msg $tmpmh xml patdemoquery urn\$xmltypes.clinical.bjc.org\$getPatientsDemographicsBySummaryResponse]
# while something to fetch in….get patient demographic data
set lastname “”
set valPointer [grmfetch $ghIn nm1:getPatientsDemographicsBySummaryResponse.nm1:patient(0).nm1:patientDemographics.nm1:patientName.nm1:last.#text]
set lastname [string trim [datget $valPointer VALUE] \”]
set firstname “”
set valPointer [grmfetch $ghIn nm1:getPatientsDemographicsBySummaryResponse.nm1:patient(0).nm1:patientDemographics.nm1:patientName.nm1:first.#text]
set firstname [string trim [datget $valPointer VALUE] \”]
set middlename “”
set valPointer [grmfetch $ghIn nm1:getPatientsDemographicsBySummaryResponse.nm1:patient(0).nm1:patientDemographics.nm1:patientName.nm1:middle.#text]
set middlename [string trim [datget $valPointer VALUE] \”]
if {![string equal $middlename “”]} {
set middleinit [string range $middlename 0 0]
set patientname [cconcat $lastname \^ $firstname \^ $middleinit ]
} else {
set patientname [cconcat $lastname \^ $firstname ]
}
set dob “”
set valPointer [grmfetch $ghIn nm1:getPatientsDemographicsBySummaryResponse.nm1:patient(0).nm1:patientDemographics.nm1:DOB.#text]
set dob [string trim [datget $valPointer VALUE] \”]
if {![string equal $dob “”]} {
set dobccyy [string range $dob 0 3]
set dobmm [string range $dob 5 6]
set dobdd [string range $dob 8 9]
set dob [cconcat $dobccyy$dobmm$dobdd]
}
set sex “”
set valPointer [grmfetch $ghIn nm1:getPatientsDemographicsBySummaryResponse.nm1:patient(0).nm1:patientDemographics.nm1:sex.nm1:longDisplayValue.#text]
set sex [string trim [datget $valPointer VALUE] \”]
if {![string equal $sex “”]} {
set sex [string range $sex 0 0]
}
# destroy any handles we dont need anymore
msgdestroy $tmpmh
grmdestroy $ghIn
set datHandleList [datlist]
foreach handle $datHandleList {
datdestroy $handle
}
set grmHandleList [grmlist]
foreach handle $grmHandleList {
grmdestroy $handle
}
}
}
}
if {![string equal $errorInformation “”]} {
puts “Error Info: $errorInformation”
}
}
}
if {![string equal $fatalErrorMsg “”]} {
puts $error_fh “$msg had a FATAL ERROR IN WEB SERVICE CALL. ERROR WAS $fatalErrorMsg”
puts “CHECK WITH CDR TEAM FOR ISSUES RELATING TO THIS WEB SERVICE…”
set errorfound 1
incr errorcnt
close $error_fh
close $output_fh
catch {exec rm -f $outputFile} catch_return
} else {
############ DocumentService query #################################################################################################
puts “found: $firstname $lastname $dob $sex”
puts “lookup: $upi – $repositoryId – $key”
puts “—————————————————————————–”
puts ” — begin query # 2 DocumentService for upi $upiDisplay –”
puts ” ”
#————————————————————————
# Now we process the list of document keys found in the first WS call
#————————————————————————
set errorInformation {}
set outputMsgCtr 0
# set up the web service call to get the document associated with the current key.
set soapEnv “<?xml version=’1.0′ encoding=’UTF-8′?>”
append soapEnv “<soapenv:Envelope ”
append soapEnv “xmlns:soapenv=\”http://schemas.xmlsoap.org/soap/envelope/\” xmlns:urn=\”urn:xmltypes.clinical.bjc.org\”>”
append soapEnv “<soapenv:Header/>”
append soapEnv “<soapenv:Body>”
append soapEnv “<urn:getDocument>”
append soapEnv “<urn:repositoryKey>$key</urn:repositoryKey>”
append soapEnv “<urn:repID>$repositoryId</urn:repID>”
append soapEnv “<urn:thumbnails>false</urn:thumbnails>”
append soapEnv “<urn:converted>false</urn:converted>”
append soapEnv “<!–Optional:–>”
append soapEnv “<urn:patient>”
append soapEnv “<urn:UPI>$upi</urn:UPI>”
append soapEnv “</urn:patient>”
append soapEnv “<urn:headerOnly>false</urn:headerOnly>”
append soapEnv “<urn:linkData>false</urn:linkData>”
append soapEnv “</urn:getDocument>”
append soapEnv “</soapenv:Body>”
append soapEnv “</soapenv:Envelope>”
set soapEnv [string trim $soapEnv]
if {[file exists “/hci/bin/monitor/productionserver”]} {
set WSserver “https://clinws.carenet.org/gfwsprod2/DocumentService”
} else {
set WSserver “https://clinwstest.carenet.org/gfwstest/DocumentService”
set WSserver “https://clinwstest.carenet.org/gfwsuser2/DocumentService”
set WSserver “http://clinws.carenet.org/gfwsprod2/DocumentService”
}
set httpHeaders “”
set httpBody “”
set response “”
lappend httpHeaders “Content-Type: text/xml; charset=utf-8”
lappend httpHeaders “SoapAction: submitOrder”
set datea [clock format [clock seconds] -format %Y%m%d]
set timea [clock format [clock seconds] -format %H%M%S]
# issue web service call to get document for the key
catch { curl::transfer -url $WSserver \
-httpheader $httpHeaders \
-postfields $soapEnv \
-timeout 20 \
-verbose 0 \
-ipresolve v4 \
-sslverifypeer 0 \
-bodyvar httpBody } response
set dateb [clock format [clock seconds] -format %Y%m%d]
set timeb [clock format [clock seconds] -format %H%M%S]
set time_diff [expr [clock scan “$dateb $timeb”] – [clock scan “$datea $timea”]]
puts “[whereAmI] Elapsed Time – document key fetch: $time_diff : $repositoryId | $key ”
##————————————————————————
## Check curl response for error if none check http body for error.
## If none echo error and exit.
##————————————————————————
#puts “**** WEBSERVICE DocumentService RESPONSE : HTTP: $httpBody”
if { $response != 0 } {
puts “**** WEBSERVICE DocumentService RESPONSE : SOAP: $response – $key : $repositoryId ”
puts “—————————————————————————–”
}
puts ” ”
set errorInformation {}
if { $response == 7 } {
puts “ERROR: Could not connect to Web Services. Server may be down.”
set fatalErrorMsg “Could not connect to Web Services. Server may be down for document retreival.”
} else {
if { $response == 28 } {
puts “ERROR: Connection to server timeout.”
set fatalErrorMsg “Connection to server timeout in document retreival.”
} else {
if { $response != 0} {
##————————————————————
## curl error code can be found here:
## http://curl.haxx.se/libcurl/c/libcurl-errors.html
##————————————————————
puts “ERROR: An unidentified response of $response while fetching $repositoryId – $key ”
set fatalErrorMsg “An unidentified error occured error code: $response – in document retreival.”
} else {
set errorInformation {}
##————————————————————
## Checks for errors with the web server. Puts error to the
## log file.
##————————————————————
##
## Even if the response was 0, there could be an error.
## If the returned httpBody does not begin with the soap envelope tag,
## there was an error, attempt to get the text of the error from <title>.
if {[cequal [string first “<S:Envelope” $httpBody] -1]} {
set response 101
set errorInformation {}
lappend errorInformation {Error condition not read}
lappend errorInformation {Error message text not read}
if {![cequal [string first “<title>” $httpBody] -1]} {
set t1 [string first “<title>” $httpBody]
set t2 [string first “</title>” $httpBody]
incr t1 7
incr t2 -1
set text [string range $httpBody $t1 $t2]
set errorInformation [lreplace $errorInformation 0 0 “$text”]
}
if {![cequal [string first “<p>” $httpBody] -1]} {
set p1 [string first “<p>” $httpBody]
set p2 [string first “</p>” $httpBody]
incr p1 3
incr p2 -1
set text [string range $httpBody $p1 $p2]
set errorInformation [lreplace $errorInformation 1 1 “$text”]
}
puts “[lindex $errorInformation 0] : [lindex $errorInformation 1]”
}
# Now parse out the returned xml
set index1 [string first “<S:Body” $httpBody]
set index2 [string first “</S:Body>” $httpBody]
set xmlmsg [string range $httpBody [expr $index1 +8] [expr $index2 – 1] ]
if {[string first “<document>” $xmlmsg] < 0} {
puts “document key $key did not return a document to process…skipping this key”
continue
}
# replace all the carriage returns with \.br\ so cloverleaf can read it without error
regsub -all {&\#xD\;} $xmlmsg {\\.br\\} xmlmsg
set tmpmh [msgcreate data]
msgset $tmpmh $xmlmsg
# process the xml here
set ghIn [grmcreate -msg $tmpmh xml radquery urn\$xmltypes.clinical.bjc.org\$getDocumentResponse]
set document “”
set valPointer [grmfetch $ghIn nm1:getDocumentResponse.nm1:document(0).nm1:eDocument.0(0).nm1:part(0).0(0).nm1:partContent.#text]
set document [string trim [datget $valPointer VALUE] \”]
set status “”
set valPointer [grmfetch $ghIn nm1:getDocumentResponse.nm1:document(0).nm1:eDocument.nm1:status.nm1:longDisplayValue.#text]
set status [string trim [datget $valPointer VALUE] \”]
# destroy and left over handles
msgdestroy $tmpmh
grmdestroy $ghIn
set datHandleList [datlist]
foreach handle $datHandleList {
datdestroy $handle
}
set grmHandleList [grmlist]
foreach handle $grmHandleList {
grmdestroy $handle
}
# create the message with the document
set mhNew {}
set filemsg {}
set messageTs [clock format [clock seconds] -format %Y%m%d%H%M%S]
incr outputMsgCtr
#set random [expr {int(100 * rand())}]
set outControl_id [cconcat “$controlIDbase” “-” $outputMsgCtr]
##—————————————————–
## Create the Document
##—————————————————–
regsub -all {\\.br\\} $document “\n” document
regsub -all {\\.nf\\} $document {} document
regsub -all {\\.fi\\} $document {} document
set OBXSegGroup {}
# for dislpaying in the log:
set OBXSegGroupPrint {}
foreach line [split $document \n] {
set OBXSeg $line
set OBXSegGroup [cconcat $OBXSegGroup $OBXSeg \r]
# For displaying in the log
set OBXSegGroupPrint [cconcat $OBXSegGroupPrint $OBXSeg ” “]
}
# Create the output file.
set filemsg $line
exec /hci/bin/b64.o -d $document filemsg
puts $output_fh $filemsg
close $output_fh
}
if {![string equal $errorInformation “”]} {
puts “Error Info: $errorInformation”
}
}
}
if {![string equal $fatalErrorMsg “”] } {
puts $error_fh “$msg had a FATAL ERROR IN WEB SERVICE CALL. $fatalErrorMsg”
puts “CHECK WITH CDR TEAM FOR ISSUES RELATING TO THIS WEB SERVICE…”
set errorfound 1
incr errorcnt
close $error_fh
close $output_fh
catch {exec rm -f $outputFile} catch_return
} else {
close $error_fh
catch {exec rm -f $errorFile} catch_return
}
}
if {$errorfound} {
puts “closing output file and deleteing it…”
catch {close $output_fh} catch_return
catch {exec rm -f $outputFile} catch_return
}
}
set date2 [clock format [clock seconds] -format %Y%m%d]
set time2 [clock format [clock seconds] -format %H%M%S]
set time_diff [expr [clock scan “$date2 $time2”] – [clock scan “$date1 $time1”]]
puts “[whereAmI] Total Query Elapsed Time in seconds: $time_diff”
puts ” ”
puts “….. logging for UPI $upi ends here ……..”
puts ” ”
close $inputFh
catch {exec rm -f $inputFile} catch_return
puts “catch returned from removing $inputFile”
}
}
time {
}
shutdown {
}
default {
puts “Unknown mode ‘$mode’ in tpsBooneCDRQry”
}
}
return $dispList
}
Thanks
-Peter
Sorry Pete just too much to deal with without knowing what the input is. 🙂
A lot of superfluous code. All of your files should be open with binary option.
Why are you using exec to delete files. Use Tcl for that. Why aren’t you using the base-64 commands provided by Tcl.
<pre>package require <b>base64</b></pre>
<pre><b>::base64::decode</b> <u>string
</u>If I can help more send me an email: cbursell@fastem.com</pre>
Too much old school here when I mentioned the base64 package 🙂
FYI, you do not need the base64 package to do base64 conversions in Cloverleaf. The commands encode and decode are available for that
encode charlie
=> Y2hhcmxpZQ==
decode Y2hhcmxpZQ==
=> charlie
Peter:
I accidently deleted the mail message you sent. Now I do not have your email address. Please resend