Save JavaScript generated bar code to folder on web server, ColdFusion and Javascript

Hello all,

So I am working on creating an ID card that gets generated from a ColdFusion app. I am using Cfdocument to create the final product which can be printed on a card printer. As well as JsBarcode to create the bardcodeds based on an Id. Everything up to the pdf generation worked fine including the javascript barcode. I get a broken image icon where the barcode should be. Obviously javascript is being rendered by the browser and loaded into an image tag so I understand once everything loads to the pdf the javascript is no more.

What I need to do is before the print ID phase save the barcode that gets generated to a folder on the server. Then I can just use the saved image in the final product.

Below is the javascript code im using to generate the barcode. Im sure there is some code i can add to save the result, I just cant think of it.

<!--- in the header --->

<head>
	<meta charset="UTF-8">
	<title></title>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
	<script src="jsBarcode/EAN_UPC.js"></script>
	<script src="jsBarcode/CODE128.js"></script>
	<script src="jsBarcode/JsBarcode.js"></script>
</head>

<!--- in the body pf page--->
<div>
		<img id="barcode2"/>

		<script>$("##barcode2").JsBarcode("#Participant_ID__c#",{width:2,height:25});</script>

	</div>

Open in new window


Thanks again.
joedfuseAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

_agx_Commented:
so I understand once everything loads to the pdf the javascript is no more.

Actually it's the reverse.  Any javascript code executes after any CF code.  So once javascript kicks in, that means CF is long gone.  To save a JS generated image on the server, you need to submit another request back to the CF server. (Side note, I don't think cfdocument supports javascript).

A brief search turned up this post which says the img.src returns a base64 image that you can send to the server and save to a file.

HTML/JS
<cfset Participant_ID__c = "something here">
<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title></title>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
	<script src="https://raw.githubusercontent.com/lindell/JsBarcode/master/EAN_UPC.js"></script>
	<script src="https://raw.githubusercontent.com/lindell/JsBarcode/master/CODE128.js"></script>
	<script src="https://raw.githubusercontent.com/lindell/JsBarcode/master/JsBarcode.js"></script>
	
	<script type="text/javascript">
		function saveImage(imageID){
            console.log("saveImage function called");
            $.ajax({
                type: "POST",
                data: { base64Image : $("#"+ imageID).attr('src') },
				dataType: "json",
                url: "YourComponent.cfc?method=saveImage&returnFormat=json",
                cache: false,
                success: function(response) {
					console.log(response);
					// display saved image result on screen (debugging only)
					$("#savedStatus").html("WasSaved? "+ response.WASSAVED +"<br> FileName: "+ response.FILENAME);
                },
                error: function(data) {
                    console.log(data);
                }
            });
        }
	</script>
	
</head>
<body>
<!--- in the body pf page--->
<div>
		<img id="barcode2"/>

		<script>$("#barcode2").JsBarcode("#Participant_ID__c#",{width:2,height:25});</script>
		<a href="javascript:saveImage('barcode2')">Save to Server</a>
		
		<h3>SaveImage() Result:</h3>
		<div id="savedStatus"/>
	</div>
</body>
</html>

Open in new window


YourComponent.cfc
<cfcomponent>

	<cffunction name="saveImage" access="remote" returntype="struct">
		<cfargument name="base64Image" type="string" required="true">
		<cfset Local.result = { wasSaved=false, error="", fileName=""}>

		<cftry>
		    <!--- create unique file name ---> 
			<cfset Local.result.fileName = createUUID() &".jpg">
		    <!--- save image to file in current directory  ---> 
			<cfset Local.img = ImageReadBase64(arguments.base64Image)>
			<cfset ImageWrite( Local.img, ExpandPath(Local.result.fileName))>
		    <!--- update status ---> 
			<cfset Local.result.wasSaved = true>
			
			<cfcatch type="any">
				<!--- do something on error ... ---> 
				<cfset Local.result.error = cfcatch.message>
			</cfcatch>
		</cftry>

		<!--- return result ---> 
		<cfreturn Local.result>
	</cffunction>
</cfcomponent>

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
joedfuseAuthor Commented:
Nice catch on that article.

I am not all that familiar with Javascript beyond the basic ui stuff. If I am understanding you, you are  taking the data that makes up the image and writing it to a file when you click the link you added below the barcode. Where is the image being saved before your code? Again I have not worked with canvas stuff but I assumed since you could see the image on that page it had to get saved somewhere and I could access that in the jsBarCode properties. Obviously I was wrong there lol

How would I go about auto saving the file without the user knowing... the link I want them to click is the cfdocument that will use the image and line everything up so the ID printer can print the card.

Also, if I wanted to learn more on what you did above, what do you recommend looking up? Ajax, HTML5, jQuery etc...

Thanks
joedfuseAuthor Commented:
Oops forgot something else..

I assume I can set the folder and the filename by passing the barcode data (Participant_ID) and the target location to the component? Or does i have to use the root where my page is?

I am surprised that the base64 img isnt accessible to cfimage I think thats why I was stumped... Been looking for a way to use what the plugin gave me without using its source code.
_agx_Commented:
EDIT:

it had to get saved somewhere and I could access that in the jsBarCode properties

Its essentially in memory at this point. (Though with HTML5 you can store stuff for later usage in one of its "storage" areas) ). However, like any client side code, it is totally disconnected from the CF server. So if you want to manipulate the data from CF, you have to make a new request back to the CF server. To do that without leaving the page means ajax.

How would I go about auto saving the file without the user knowing... the link I want them to click is the cfdocument that will use the image and line everything up so the ID printer can print the card.

Listen for a javascript event, like image.onload.  When that event is triggered, call saveImage() inside the handler to automatically send the loaded image to the CF server.  OR you could send it when they click the link to generate the cfdocument.  All depends on the flow.

Also, if I wanted to learn more on what you did above, what do you recommend looking up? Ajax, HTML5, jQuery etc...

Technically it's all of the above. The barcode generation is a mix of HTML5 and jQuery, while the saveImage() function is pure jQuery (doing an ajax call).  Definitely get familiar with the jQuery $.ajax({...}) method. It's pretty commonly used for communication between browser and CF server. Think of it as the javascript version of cfhttp ;-)


I assume I can set the folder and the filename by passing the barcode data (Participant_ID) and the target location to the component? Or does i have to use the root where my page is?

You can, but I'd recommend NOT sending information about the server (folder structure, etc..) via ajax for security reasons.  (Assume anything in the URL can be manipulated for nefarious purposes).  If you're only using the image to generate the pdf, then the client doesn't need to know where you're storing the images or under what file name.  Just assign the paths needed within the CF code.  Images can be stored anywhere on the server you want, as long as they're  accessible to the CF server.

I am surprised that the base64 img isnt accessible to cfimage I think thats why I was stumped... Been looking for a way to use what the plugin gave me without using its source code.

Well ... I think you may be confusing the order of operations and relationship between CF and javascript: in short, there is none.  They're totally separate.  The CF server executes any cfml first, converts it into html, and then it's out of the picture.  Afterward, the browser runs the generated html.   So there's no way CF could know anything about the bar code image in the browser. Not unless you submit another http request AFTER the browser loads the image.

To illustrate with a silly example, let's take your barcode generating page.  Presumably it's a mix of CFML, HTML and javascript saved to a .cfm file.  We'll call it "http://yourserver/testBarCode.cfm"

<!--- demo purposes, set a CF variable --->
<cfset Participant_ID__c = "some value here">
....
<head>
	<meta charset="UTF-8">
	<title></title>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
	<script src="jsBarcode/EAN_UPC.js"></script>
	<script src="jsBarcode/CODE128.js"></script>
	<script src="jsBarcode/JsBarcode.js"></script>
</head>
...

<!--- this part contains a CF variable which must be evaluated --->
<cfoutput>
<div>
    <img id="barcode2"/>
    <script>$("##barcode2").JsBarcode("#Participant_ID__c#",{width:2,height:25});</script>
</div>
<cfoutput>

Open in new window


When you load that page in your browser, the basic process goes something like this:

User Bob: (Opens his browser and loads http://yourserver/testBarCode.cfm)
Browser: Hey Web Server (http://yourserver), can you send me this page please:  /testBarCode.cfm ?
Web Server:  Sure.  That's a CFML script. I don't handle those, but I know a guy who does.  Hang on a second.
Web Server: Knock, knock, CF Server. I've got a job for you. Some guy wants to view a .CFM page. Can you process that for me?
CF Server: Sure.  Let me execute the CFML code first and translate it for ya'.... Okay, done. Here's the output. Nothing but pure HTML/Javascript!

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title></title>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
....
</head>
<body>
<div>
      <img id="barcode2"/>
      <!-- notice the CF variable was interpreted and replaced with a literal string? -->
      <script>$("#barcode2").JsBarcode("something here",{width:2,height:25});</script>
      <a href="javascript:saveImage('barcode2')">Save to Server</a>
      <h3>SaveImage() Result:</h3>
      <div id="savedStatus"/>
</body>
</html> 

Open in new window


Web Server: Got it, CF Server.
CF Server: Then I'm out of here.  (Fraiser has left the building...) [Disconnects]
Web Server: Hey Browser, here's the HTML you asked for
Browser: Got it.
Web Server: Okay, my job here is done.  [Disconnects]
Browser: (Renders HTML/Javascript in main window)
User Bob: "Nice! I can see the barcode."

THE END

So as you can see, at the time the CFML runs, the bar code doesn't even exist yet. By the time it does, the CF server has already disconnected. The only way to make CF aware of it is to wait until the image is rendered in the browser. Then send a new http request back to the CF server via ajax.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.