Enforcing image width after upload - coldfusion

After doing a cffile action="upload", I'd like to check the width (assuming it's a image). I'm currently using CF8.
Is there a built-in function to get the width of an image? If there's a built-in function in CF9, I guess I need to know that for when we update.

According to LiveDocs, the functionality exists in CF8.
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_h-im_32.html#5164681
The example provided by Adobe should get you going:
<!--- This example shows how to retrieve information associated with the image. --->
<!--- Create a ColdFusion image from a JPEG file.--->
<cfimage source="../cfdocs/images/artgallery/jeff05.jpg" name="myImage">
<!--- Retrieve the information associated with the image. --->
<cfset info=ImageInfo(myImage)>
<cfdump var="#info#"></cfdump>
<p>height = <cfoutput>#info.height#</cfoutput>
<p>width = <cfoutput>#info.width#</cfoutput>
<p>source = <cfoutput>#info.source#"</cfoutput>

Related

Working with ColdFusion - Looping a procedure

I'm wondering if there is a better way to do what I'm doing. It works but I feel there should be a better way. If my query result in 20K records for example, I'm getting "The request has exceeded the allowable time limit Tag: CFQUERY"
<cfquery name="GetMyRecords" datasource="MyDSN">
SELECT idnumber,PrefAddr,...more colums
FROM um_valid
WHERE userid = <cfqueryparam cfsqltype="cf_sql_varchar"
value="#session.userid#">
AND session_id = <cfqueryparam cfsqltype="cf_sql_numeric"
value="#session.Session_Id#">
AND status NOT IN (<cfqueryparam cfsqltype="cf_sql_varchar"
value="X,C">)
</cfquery>
I also have an existing store procedure that expect some values from the query to do what it's supposed to do. So I'm looping it like this:
<cfloop query="GetMyRecords">
<cfstoredproc procedure="MyProc" datasource="MyDSN">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR"
dbvarname="#id_number" value="#Trim(idnumber)#">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR"
dbvarname="#Aaddr_pref_ind" value="#Trim(PrefAddr)#">
----- still more params to be passed----
</cfstoredproc>
</cfloop>
Does ColdFusion has a better technique to avoid either time out error or 500 error?
Like another poster mentioned, reducing the number of database calls should be a priority to you. I suggest joining data (if possible) in your first query rather than looping your query and querying again.
To fix the time issue, you can put requestTimeout in your page to override the default timeout. The time is in seconds.
<cfsetting requestTimeOut = "600">
See this explanation.
Your current approach is to make 1 query, which contains n records. Then loop over that record set, calling a query for each record. This results in your calling n + 1 queries per request. As the volume of data returned by your first query increases, so too does the volume of overall queries made to the database. In your case, you're trying to make 20,001 calls to the database in a single request.
Ideally, you need a solution that involves one call to a stored procedure with a properly optimized query that can return all of your data in a single record set. If you don't need to dump all the data onto the page at the same time, then create a paginated query that will return x number of records per page. Then the user can go page by page through the query or provide a search form with additional filters to allow the user to reduce the overall size of the records returned.
Need to see full queries to give you an example, but in general, this is a really useful thing in CF to help you out!
You need to look into the attribute called group. This lets you specify a column to group your output by. This actually will eliminate the need for the stored proc you are calling entirely.
The way it works is letting you create sub-set outputs based on grouping. So for example, you could do this with your id's and output that group.
You can also have multiple of these and have header and footer sections for each one for display purposes or just logic manipulation.
This lets you query the entire dataset and then manipulate it in the loop without having subqueries which is ultra inefficient and cringe worthy.
This is something quite unique to ColdFusion, check it out!
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7ff6.html

CFSEARCH Solr Collection limitations

I have migrated a Verity based CFSEARCH solution over to Solr based CFSEARCH solution and finding that Solr is not returning all results when searching against multiple collections. I am going to work around this via running separate CFSEARCH calls and consolidating my results but wanted to know if a better work around exists that would allow things to work via just one CFSEARCH call. Code that does not return the proper results is pretty simple:
<CFsearch NAME="EMCSearch"
COLLECTION="apropos,certegy,cmco,conoco,contracts,corpbadge_pki,cust_train,delft_dc,documentation_help,dsvcs,grti,gts,infosys,mgmt_tools,pers,processes,scc,sd,slb,srv_desc,tips,voip,WAN_Work_Procedures,west"
CRITERIA="#LCase(searchfor)#">
That returns a record count of 23 results. If I however change things to this I get a combined record count of 76:
<cfset lstCols = "apropos,certegy,cmco,conoco,contracts,corpbadge_pki,cust_train,delft_dc,documentation_help,dsvcs,grti,gts,infosys,mgmt_tools,pers,processes,scc,sd,slb,srv_desc,tips,voip,WAN_Work_Procedures,west" />
<cfloop list="#Variables.lstCols#" index="Col">
<CFsearch NAME="EMCSearch"
COLLECTION="#Col#"
CRITERIA="#LCase(searchfor)#">
</cfloop>

Unable to display the data returned by a sql function in ColdFusion

We are trying to display a record set in a webform using the cffunction in ColdFusion.
But we are unable to display the ouptut..We are just getting a single value(last value in the record set).The sql function is returning ref cursor.Please help us resolve this issue!
thanks!
<cfset bare_drive_result = functionname('x','y')>
<cffunction name="functionname" hint="Gets all customer from the database" returntype="query">
<cfargument name="sPcwQua" type=any>
<cfargument name="sPcwAcc" type=any>
<cfquery name="getRkBareDrive" datasource= "#PCW_dsn#">
select pacakagename.functionname('#sPcwQua#','#sPcwAcc#') bare_drive_result
from dual
</cfquery>
<cfreturn getRkBareDrive>
</cffunction>
<cfoutput>#getRkBareDrive.bare_drive_result#</cfoutput>
You have a scoping issue. The name of the query inside your method is getRKBareDrive, however, you are setting the result of that function call to another variable name - bare_drive_result.
The code would actually be:
<cfoutput query="bare_drive_result">#bare_drive_result.bare_drive_result</cfoutput>
And inside your function, you need to add this line just after the cfargument tags:
<cfset var getRkBareDrive = "" />
However, that does not solve your immediate problem. Have you tried doing:
<cfdump var="#bare_drive_result#" />
to see what is actually returned to ColdFusion
Everything #Scott Stroz said in his answer is true - 1) you are confusing variable names between the code and the inline function, 2) use a var scope to define the getRKBareDrive variable inside your function (not directly part of the issue being an inline function, but good practice), and 3) try to CFDUMP the result instead of CFOUTPUT it. However I don't believe the core issue is addressed, which lies with this part of your question:
The sql function is returning ref cursor
So one glaring issue is that you are returning a REFCURSOR not a simple value, so you cannot just CFOUTPUT it but instead need to take certain steps so ColdFusion knows it is a query set. REFCURSOR can be returned in calls from Stored Procedures via CFPROCRESULT (or via CFPROCPARAM type="OUT" CFSQLType="CF_SQL_REFCURSOR" if it's a returned parameter not a result).
So... try coverting the CFQUERY call to a CFSTOREDPROC. Here's some sample code that assumes you can call your package/function directly as a stored proc vs through a query. I removed the inline function as it's adding too much complexity here (again see Scott's answer) -- just try bare code as a way to get the call working.
<cfstoredproc procedure="pacakagename.functionname" datasource= "#PCW_dsn#">
<cfprocparam type="IN" CFSQLType="CF_SQL_VARCHAR", value="x">
<cfprocparam type="IN" CFSQLType="CF_SQL_VARCHAR", value="y">
<cfprocresult name="bare_drive_result" >
</cfstoredproc>
<cfdump var="#bare_drive_result#">
If you see results in the dump, you should be able replace the dump and output the fields within the ref cursor just like a normal CFQUERY result within a CFOUTPUT query="bare_drive_result" call.
From CF8 documentation on CFPROCRESULT:
CFML supports Oracle 8 and 9 Reference Cursor type, which passes a
parameter by reference. Parameters that are passed this way can be
allocated and deallocated from memory within the execution of one
application. To use reference cursors in packages or stored
procedures, use the cfprocresult tag. This causes the ColdFusion JDBC
database driver to put Oracle reference cursors into a result set.
(You cannot use this method with Oracle's ThinClient JDBC drivers.)
Try this
<cfoutput query="getRkBareDrive">#getRkBareDrive.bare_drive_result#</cfoutput>
I suspect Scott's solution will help you out, though if you are still having issues you can add a result parameter to your query to help troubleshoot & see exactly what is being passed.
<cfquery name="getRkBareDrive" datasource= "#PCW_dsn#" result="qryname">
then dump that:
<cfdump var="#qryname#" />
The returned structure should show you the query passed in, number of results etc [i suspect it is actually returning only one], see the full description here: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_p-q_17.html

Speed up QoQ's or an alternative approach?

I am building an application that performs a master query with many joins. This query data is then available to the whole application to play around with in a global variable. The query refreshes or gets the latest result set on each page refresh; so it's only in the same state for the life of the request.
In other parts of this application, I sometimes run 100's of QoQ's on this data - usually the result of recursive function calls. However, while QoQ is a great feature, it's not too fast and sometimes page loads can be between 3000 - 5000 ms on a bad day. It's just not fast enough.
Is there any kind of optimisation techniques I can do to make QoQ perform faster or perhaps an alternative method? I read an interesting article by Ben Nadel on Duplicate() function - is there any scope for using that and if so, how?
I would love to hear your thoughts.
Don't worry about crazy suggestions, this is a personal project so I'm willing to take risks. I'm running this on Railo compatible with CF8.
Many thanks,
Michael.
Without seeing the code and complexity of the QoQs it is hard to say for sure the best approach, however one thing you can do is use a struct to index the records outside of a QoQ. Much of the overhead of using QoQ is building new query objects, and using a struct write only approach is much more efficient than for example looping over the original query and making comparisons.
For example:
<!--- build up index --->
<cfset structindex = {} />
<cfset fields = "first,last,company" />
<cfloop list="#fields#" index="field">
<cfset key = "field:#field#,value:#q[field][currentrow]#" />
<!--- initialize each key (instead of using stuctkeyexists) --->
<cfloop query="q">
<cfset structindex[key] = "" />
</cfloop>
<cfloop query="q">
<!--- update each key with list of matching row indexes --->
<cfset structindex[key] = listappend(structindex[key], currentrow) />
</cfloop>
</cfloop>
<!--- save structindex to global variable --->
<!--- output rows matching index --->
<cfset key = "field:company,value:stackexchange" />
<cfoutput>
<cfloop list="#structindex[key]#" index="row">
#q.last[row]#, #q.first[row]# (#q.company[row]#)<br />
</cfloop>
</cfoutput>
If this doesn't match your need provide some examples of the QoQ statements and how many records are in the main query.
First, I would look at the time taken by the master query. If it can be cached for some mount of time and is taking a good chunk of the pageload time, I would cache it.
Next, I would look at the recursive calls. If they can be made iterative, that would probably speed things up. I realize this is not always possible. I would be surprised if this isn't your biggest time sink. without knowing more about what you are doing, though, it's hard to help you optimize this.
I might also consider writing some of the recursive QoQs s stored procedures on the DB server, which is designed to handle data quickly and slice and dice efficiently. CF is not -- QoQs are very useful, but not speed demons (as you've noted).
Finally, I would look for straightfoward filters, and not use QoQ. Rather, I would just run a loop over the master query in a standard cfoutput tag, and filter on the fly. This means you are looping over the master query once, rather than the master query once and the result query once.
There are two primary solutions here. First you could do something in CF with the records outside of QoQ. I posted my suggestion on this already. The other is to do everything in the db. One way I've found to do this is to use a subquery as a temp table. You can even keep the sql statement in a global variable and then reference it in the same places you are currently with the QoQ but doing a real query to the database. It may sound slower than one trip tothe DB and then many QoQ but in reality it probably isn't if indexed efficiently.
select *
from (
#sqlstring#
) as tmp
where company = 'stackexchange'
I have actually done this for system with complex criteria for both what records a user should have access to and then also what they can filter for in those records. Going with this approach means you always know the source of the inner records instead of trying to ensure every single query is pulling correctly.
Edit:
It is actually safer (and usually more efficient) to use queryparams when ever possible. I found this can be done by including a file of the sql statement...
select *
from (
<cfinclude template="master_subquery.cfm" />
) as tmp
where company = 'stackexchange'

Upload File to Database in ColdFusion

I simply would like to upload a file to my database using ColdFusion. I understand how to upload an image to a directory, but I would like to place it directly in the database.
I have set a database field to varbinary(MAX) to accept the image and have the stored procedure to insert it. Currently my code for uploading the image to my file system is:
<cfif isdefined("form.FileUploadImage")>
<cffile action="upload" filefield="FileUploadImage" destination="#uploadfolder#" nameconflict="overwrite" accept="image/*" >
</cfif>
I've obviously left some of the supporting code out, but really all I need to do is get a binary representation of the file stored in memory, instead of the file system.
Any experts out there that can help?
Thanks,
George
Something like this?
<cfquery>
INSERT INTO Image (Jpg)
VALUES (
<cfqueryparam CFSQLType="CF_SQL_BLOB"
value="#ToBase64(FileReadBinary(uploadedFilePath))#">
</cfquery>
Later if you want to stream the image back to the browser, use <cfimage> (CF8+)
The way to bypass saving file to the file system:
<cfqueryparam cfsqltype="cf_sql_blob"
value="#FileReadBinary(FORM.FileUploadImage)#">