In this post I am going to show you how to create a mobile application using ColdFusion Splendor that can take a picture and upload the picture to CF server. This application uses Camera and File APIs.
The application is very simple – it has two buttons, one to take picture and the other one to set URL where pictures are to be uploaded. You can set URL of the server before taking a picture or after, just before it is to be uploaded. Once the URL is set, it is stored in the localStorage and will be remembered. There is a messages div where the application displays messages about different operations it is performing.
Here is HTML UI code in the index.cfm –
Event handler for the setServerURLBtn first checks if server url is already stored in the localStorage. If yes, it initializes input field with that url. After user enters the URL, this function sets it to localstorage.serverUrl variable.
Event handler for takePictBtn calls takePictureAndUpload function which we will see in the cfclient block later. Note that I am not assigning takePictureAndUpload directly to the event handler because when that code is executed by the browser, cfclient block is not initialized yet and so takePictureAndUpload function would not be available.
Remaining code in this file is cfclient code. First we enable device APIs (required because we are going to use Camera APIs) in cfclientsettings tag. Then we start cfclient block.
We will now add functions in the cfscript block of cfclient. The first function is takePictureAndUpload –
cfclient.camera.getPicture() launches device’s camera application. Depending on options passed to this function, it either returns path of the saved picture or picture data in base64 format. In this application I am not passing any options and the API returns path of the picture file.
PhoneGap supports two kinds of file system types – persistent and temporary. Files generated by device APIs are generally stored in the temporary file system. As the name suggest, all files stored in this file system are temporary in nature and many not be available later. So I need to move the picture file from temporary file system to persistent file system. I will do that in copyFileFromTempToPersistentFileSystem that we will see shortly.
Once I get path of the file (returned by copyFileFromTempToPersistentFileSystem) in persistent file system, I call another function, uploadFileToServer and then delete temporary file.
Here is the code for copyFileFromTempToPersistentFileSystem function –
And uploadFileToServer function –
This function first checks if user has already entered URL where files is to be uploaded. If it is not set, then it prompts user to enter the URL. Then it sets form field options in uploadOptions struct.
Image data would be sent in a form field assigned to fileKey field. In this application it is “uploadedPicture”. As per PhoneGap docs fileName field tells server the name to be used when saving the uploaded file. But I found that this field is not passed to the server, or server does not save file with the name assigned to this field. I have not investigated if the bug is in PhoneGap or cfclient implementation.
cfclient.file.upload function actually sends file data to the server. Third and fourth argument to this function are success and error calbacks respectively. In this example those are onFileUploaded (success callback) and uploadError (error callback) functions.
That completes the client side code. Now let’s see how the server-side code (to receive uploaded file and save it on the server) could be written (it is in fileUploadHandler.cfm in server folder of this project) –
Note that the uploaded file date is stored in the form field “uploadedPicture”, as specified in the client side code in uploadFileToServer function. The above code saves picture file in the same folder as the CFML file processing it.
I have provided links to download Android application and Thunder project below. If you download the project, you will see that client side code is in the root folder of the project and server-side code is in a subfolder called ‘server’. There is Application.cfm in the root of the project and another one in the ‘server’ folder. It is important that client and server CFML code have their own Application.cfm.
I have added Application.cfm in the project root so that I could run this application in the Shell app. But since server folder is a child of project folder, it would use Application.cfm in the project root, if it does not have its own Application.cfm. So I included an empty Application.cfm in the server folder too. It would be better to have client and server code in completely independent folders, but in this case I added server folder in the root of client folder to simplify packaging of the project.
You will find all uploaded pictures from this application in CFMobilePhotoApp/server folder on the server.
When you package the application in Thunder, make sure you select only index.cfm in project properties->ColdFusion Mobile Project->Resource Selection tab.