The Coldfusion Open Source Forums
Home | ImageCFC | CFFM | BlogCFM | CFMBB | CFOpenMail / ImapCFC | CFOpenChat
Forums | Profile | Inbox | Members | Chat | Search | Login | RSS
Vivio Technologies Dedicated Hosting
New Topic Reply Subscription Options   Previous Page  Page: 1   Previous Page

Forums: ImageCFC Forum: BLOB Support
Created on: 04/11/07 {ts '2018-09-20 16:45:00'} Views: 27421 Replies: 17
BLOB Support
Posted Wednesday, April 11, 2007 at {ts '2018-09-20 16:45:00'}

Hello all,

I haven't used ImageCFC, and I am considering it as part of a plan to move a BlueDragon.Net site onto an Apache/ColdFusion platform.

I currently use BlueDragon and SQL Server to retrieve and store images from the web as BLOBs, then use .NET to create scaled versions of the image on the fly.

I'd like to be able to use ImageCFC to replace this functionality, but I cannot figure out from the documentation if it will be possible. The hangup seems to be getting the binary data from the BLOB into a Java image object so that ImageCFC can then work on it. If that can be accomplished,
then I think everything else will fal into place.

Thanks in advance,
Joe

RE: BLOB Support
Posted Wednesday, April 11, 2007 at {ts '2018-09-20 18:40:00'}

Unfortunately, I don't know of any way to directly get blog data into an image object ASIDE From writing the blog to a file and THEN having image.cfc read it.

Which should be fine unless you plan on serving images directly from the database.

I - and a whole lot of other people - would recommend against that.

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Thursday, April 12, 2007 at {ts '2018-09-20 09:36:00'}

BTW, there is a way to serve binary data directly..

For example:

download.cfm

<cfset attachment = session.imapCFC.download(url.folder, url.id, url.attach)>
<cfset byteArray = attachment.data>
<cfset contentLength = attachment.length>

<cfscript>
   context = getPageContext();
   context.setFlushOutput(false);
   response = context.getResponse().getResponse();
   out = response.getOutputStream();
   response.setContentType(attachment.type);
   response.setContentLength(contentLength);
   out.write(byteArray);
   out.flush();
   response.reset();
   out.close();
</cfscript>

The above code servers binary images - as long as you know the content length and mime type.

HOWEVER, this code is based on binary data retrieved from Coldfusion's CFFILE Tag with the READBINARY action.

I don't know if it would work on blobs and I doubt it will work with image objects unless you can figure out how to convert an image object to a byte array.

But maybe this will help you get started.

I still strongly recommend against serving images from the database. It's extremely bad practice. Cache the images on the file system and serve them from there, because the http server does a good job of serving files. You don't want to do database queries and perform all kinds of conversion operations in order to serve images from the database.

It will put an excessive load on the database server AND on coldfusion, it'll take up gigantic amounts of memory and it won't scale at all.

Rick

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Thursday, April 12, 2007 at {ts '2018-09-20 17:56:00'}

Let me explain why I'm serving images directly from the database. The application receives a list of a few thousand image urls and has to save a local copy of each one of those images. The application then has to create 300-px, 100-px, and 60-px versions of each image for display to users. To download the file, and create three different sizes and save each of those, would be four disk writes for each image. Of course, disk writes are very slow, and this could potentially take a long time to process the incoming lists (which will be coming in throughout the day and need to be processed when they are received). The solution to this was to store the image as a blob and write a .NET script to retrieve it, size it and display it (similar to cfcontent but with more control over the image size before displaying it). So, the <img> tag would call this page, for instance, as the source (yes, that's supposed to be a "not available" image placeholder.

This requires no disk writes, and can be adapted to display images in any size.

Is this the type of system you are describing when you say that it is bad practice and not scalable? Also, is that a general rule, or specific to Java-based CF and the JDBC?

If this is generally wrong, is there an alternative that will satisfy all the requirements I've mentioned? Maybe saving the original image as a file, and resizing and displaying when the browser calls for it? It seems like it would delay the display of the image. How efficient is imageCFC is this regard?

Thanks,
Joe

RE: BLOB Support
Posted Thursday, April 12, 2007 at {ts '2018-09-20 22:52:00'}

Unless you're only displaying those images one time and they are never displayed again, the fact that it takes four disk writes to save them to disk isn't relevant.

Is that the case? You're retrieving the image, storing it in the DB, and then displaying the resized versions only once - and those resized versions are *NEVER* displayed again?

Because if you display them multiple times, you're talking about disk READS versus vast amounts of computation operations which require memory and CPU resources.

If, in fact, those 1000 images are viewed 10 times, now you're talking about 4 disk writes, 3 computations to convert the blog to an image object, and 3 computations to resize said images. The 4 disk writes only occur once... but now you've got a query and 6 major computations. Per. That's 10,000 queries, and 60,000 computations for image resizing.

I'll guarantee you that 1 disk write and 10,000 queries, and 60,000 computations is *FAR* slower than 4 disk writes, 4 computations, and 40,000 disk reads.

But if you're not displaying the images more than once... well then maybe you do want to try to avoid the disk writes.

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Monday, April 16, 2007 at {ts '2018-09-20 20:23:00'}

Excellent point, and one I had overlooked while trying to optimize the import. I guess I'll revise the import plan. This will require saving the original file, overwriting it if the same file already exists. Creating three smaller versions and saving each of them, again overwriting if necessary. Then, when viewed, checking that the file exists before displaying it. If it does not for some reason, then checking that the full-size version exists, and if it does, creating the smaller version. Otherwise, displaying a "not available" graphic.

Using this decision-making when the image is viewed, would potentially do two things:
1) Make the application more scalable, by adding the ability to use images of different sizes later. For instance, if we add a new feature and decide to use a completely new thumbnail size, we will not have to create thumbnail images of the potentially hundreds of thousands of images already stored.
2) Possibly, allow us to completely skip the steps of creating the size versions at import time. The first time an image of a specific size is requested, it will be created. This might be a good compromise, spreading out the extra load and time between import and read.

Negative side of this: A little more than twice as many disk reads (I assume fileexists() uses a simple disk read). Also, slower load time for the first user to load a specific image.

Thanks for the input.

RE: BLOB Support
Posted Monday, April 16, 2007 at {ts '2018-09-20 21:35:00'}

Your suggestion is exactly the way I used to do things a long long time ago, and it's a good route to go.

Essentially I used a perl script which I passed an image name and some dimensions... it would then construct a thumbnail filename, and check for its existence.. if it existed, it served that file.. if not, it would create the thumbnail, and then serve it.

This was way back before I could use java for resizing =) It was pretty effective.

As for the file reads... fileExists() doesn't actually read the file, it merely checks for its existance. File systems are REALLY good at things like that.

You could check for the existance of a file ten thousand times and I seriously doubt you'd notice.

To test this theory, I ran the following code:

<cfsilent>
<cfset start = now().getTime()>
<cfloop from="1" to="10000" step="1" index="foo">
   <cfif fileExists("#expandPath(".")#/test#foo#.txt")>
      <!-- do nothing -->
   </cfif>
</cfloop>
<cfset end = now().getTime()>
</cfsilent>
<cfoutput>#end-start# milliseconds.</cfoutput>

On average, the code took about 450ms to check for the existence of 10,000 uniquely named files (none of which existed in this case).

Thats 0.045 milliseconds per fileExists() operation. Jeez... is that 45 microseconds?

It's pretty fast.

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Monday, April 16, 2007 at {ts '2018-09-20 21:45:00'}

Okay, so what do you differently, now that you ARE using Java for resizing?

RE: BLOB Support
Posted Tuesday, April 17, 2007 at {ts '2018-09-20 11:12:00'}

Well, because I can resize the images as part of the upload process, I tend to generate the thumbnails when the original images are uploaded, but of course like you said, if I wanted to change the thumbnail size I'd have to go through and resize all the images again.

The only reason I did the dynamic thumbnailing with "caching" was because I couldn't use coldfusion to resize the images... I had to use a perl script.

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Tuesday, April 17, 2007 at {ts '2018-09-20 14:32:00'}

Gotcha. Thanks for the information!

RE: BLOB Support
Posted Friday, May 25, 2007 at {ts '2018-09-20 15:18:00'}

Hya,
I'm Fabio an Italian CF programmer and I use it from 7 years, but only now I understand the power of LOB object couse I start to learn C# for work.
I read all your post, and i search all the network to find a good explanation of LOB Object in CF.
The problem is that do the upload of the file in LOB mode .. I hope that the mode I try is right any case I put there the code i write so you can bonk me on my head if i make error:


<cfif IsDefined("FORM.MM_InsertRecord") AND FORM.MM_InsertRecord EQ "form1">
<cffile action = "readbinary" file = "#Form.filesdat#"
variable="image_blob">

<cfquery datasource="4minds_sport">
INSERT INTO Gallery(Namefile, datfile)
VALUES (
<cfif IsDefined("FORM.FileNameString") AND #FORM.FileNameString# NEQ "">
#FORM.FileNameString#
<cfelse>
''
</cfif>
,
<cfif IsDefined("FORM.filedat") AND #FORM.filedat# NEQ "">
<cfqueryparam value=#toBase64(image_blob)#
CFSQLType="CF_SQL_CLOB">

<cfelse>
''
</cfif>
)
</cfquery>
<cflocation url="test.cfm">
</cfif>

The SQL process the Query and put the file on DB.
No problem here. The fact is that i cannot get the File out back
The real problem come out when I try to get them out.
I don't understand How to do that.
Can you write few line of explanation and some bits of example pls.

Really Thx
Fabio

RE: BLOB Support
Posted Friday, May 25, 2007 at {ts '2018-09-20 15:50:00'}

I definately can't... =) I've never used clobs/blogs in the database.

Maybe someone else reading can help though!

Rick

Rick Root
I'm not certified, but I have been told that I'm certifiable!

www
RE: BLOB Support
Posted Tuesday, June 5, 2007 at {ts '2018-09-20 14:11:00'}

Rick I solve the problem.
Hope that will help more people that are looking for it.
This is the code for View BLOB File


<cfquery datasource="#database#" name="FileInformation">
SELECT FileName, FileType, FileContent
FROM BlobExample
WHERE FileID = <cfqueryparam cfsqltype="cf_sql_integer" value="#URL.FileID#">
</cfquery>
<cfif FileInformation.RecordCount NEQ 1>
<cflocation url="index.cfm">
</cfif>
<cffile action="write" addnewline="no" charset="utf-8" file="C:\Temp\#FileInformation.FileName#" output="#ToBinary(FileInformation.FileContent)#" fixnewline="no">
<cfoutput>#FileInformation.FileName#</cfoutput>
<cfcontent deletefile="yes" file="C:\Temp\#FileInformation.FileName#" type="#FileInformation.FileType#">

The Upload is a simple form multipart data.
Multipart is NEEDED don't forget it

The Upload Routine


<cffile action="upload" destination="c:\temp\" filefield="form.blob" nameconflict="makeunique" >
<cfset VARIABLES.ClientFile = CFFILE.ClientFile>
<cfset VARIABLES.FullMimeType = "#CFFILE.ContentType#/#CFFILE.ContentSubType#">
<cffile action="readbinary" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#" variable="VARIABLES.FileBinaryContent">
<cfquery datasource="Training">
INSERT INTO BlobExample (FileName, FileType, FileContent)
VALUES (
<cfqueryparam cfsqltype="cf_sql_varchar" value="#VARIABLES.ClientFile#">,
<cfqueryparam cfsqltype="cf_sql_char" value="#VARIABLES.FullMimeType#">,
<cfqueryparam cfsqltype="cf_sql_blob" value="#VARIABLES.FileBinaryContent#" >
)
</cfquery>
<cffile action="delete" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#">

Now you have the best CF Script you can search on net. Hope that this will be usefull to pup up the click on you forum

Fabio Bandini
Crystal Design Studio
Via Gentili,41
47100 Forlì (FC)
Italy
Developer & Programs Analyst
ColdFusion & C# Very Happy

Edited 06/05/07 {ts '2018-09-20 14:13:00'}
RE: BLOB Support
Posted Monday, June 11, 2007 at {ts '2018-09-20 14:28:00'}

FBandini: Thanks for the post. Helped me out with a project today. Smile

RE: BLOB Support
Posted Monday, July 9, 2007 at {ts '2018-09-20 05:44:00'}

I use CF Script on Cold Fusion version 6.1 to insert File into BLOB type. It's works with Oracel9i

Quote:

<cffile action = "readbinary" file = "C:\Temp\032205\abc.pdf" variable="file_upblob">
<cfquery name="q" datasource="#session.ds#">
   insert into attachments_tbl (id,file_name,file_blob)values (
<cfqueryparam cfsqltype="cf_sql_varchar" value="9307">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="abc.pdf">,
<cfqueryparam cfsqltype="cf_sql_blob" value="#file_upblob#">)
</cfquery>

Next day I use same code and connect to Oracle 10G. It's not works. I found error message as below.

Quote:

Error Executing Database Query. [Macromedia][Oracle JDBC Driver][Oracle]ORA-00600: internal error code, arguments: [9999], [], [], [], [], [], [], []

RE: BLOB Support
Posted Wednesday, November 28, 2007 at {ts '2018-09-20 09:44:00'}

Hi Fabio,

I read your solution but I've a problem: How can I use that into cfmail?

CFMX 6.1

Thanks in advance

Regards
Stefano

-----

Ciao Fabio,

Ho letto la tua soluzione ma ho un piccolo problema: come posso usarlo dentro un cfmail?

CFMX 6.1

grazie mille

Ciao
Stefano


FBandini wrote:

Rick I solve the problem.
Hope that will help more people that are looking for it.
This is the code for View BLOB File

<cfquery datasource="#database#" name="FileInformation">
SELECT FileName, FileType, FileContent
FROM BlobExample
WHERE FileID = <cfqueryparam cfsqltype="cf_sql_integer" value="#URL.FileID#">
</cfquery>
<cfif FileInformation.RecordCount NEQ 1>
<cflocation url="index.cfm">
</cfif>
<cffile action="write" addnewline="no" charset="utf-8" file="C:\Temp\#FileInformation.FileName#" output="#ToBinary(FileInformation.FileContent)#" fixnewline="no">
<cfoutput>#FileInformation.FileName#</cfoutput>
<cfcontent deletefile="yes" file="C:\Temp\#FileInformation.FileName#" type="#FileInformation.FileType#">

The Upload is a simple form multipart data.
Multipart is NEEDED don't forget it

The Upload Routine


<cffile action="upload" destination="c:\temp\" filefield="form.blob" nameconflict="makeunique" >
<cfset VARIABLES.ClientFile = CFFILE.ClientFile>
<cfset VARIABLES.FullMimeType = "#CFFILE.ContentType#/#CFFILE.ContentSubType#">
<cffile action="readbinary" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#" variable="VARIABLES.FileBinaryContent">
<cfquery datasource="Training">
INSERT INTO BlobExample (FileName, FileType, FileContent)
VALUES (
<cfqueryparam cfsqltype="cf_sql_varchar" value="#VARIABLES.ClientFile#">,
<cfqueryparam cfsqltype="cf_sql_char" value="#VARIABLES.FullMimeType#">,
<cfqueryparam cfsqltype="cf_sql_blob" value="#VARIABLES.FileBinaryContent#" >
)
</cfquery>
<cffile action="delete" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#">

Now you have the best CF Script you can search on net. Hope that this will be usefull to pup up the click on you forum

Fabio Bandini
Crystal Design Studio
Via Gentili,41
47100 Forlì (FC)
Italy
Developer & Programs Analyst
ColdFusion & C# Very Happy

RE: BLOB Support
Posted Monday, December 17, 2007 at {ts '2018-09-20 19:07:00'}

Sorry for the late answer Stefano,

Any case you can use it on cfmail outing it on a local in web server dir, public of course, like images directory.
then you don't use the delete end section before had send the mail then at the end before redirect you proced to delete the temp file you have create.
To make it unique use the token and the session id like name for the file. You can change it easily have a look to the code.

-------------------------------------------

Fabio Bandini
Crystal Design Studio
Via Gentili,41
47100 Forlì (FC)
Italy
Developer & Programs Analyst
ColdFusion & C#

RE: BLOB Support
Posted Tuesday, February 10, 2009 at {ts '2018-09-20 08:48:00'}

I'm sorry for my big latency on BLOB Thread but Work waste my time.

Here a new way to use a BLOB Image

First we must create a picture.cfm that will recive the request of the record and generate the image


<cfquery name="Picture" datasource="DataPICS">
select img
from images
where id = #URL.id#
</cfquery>

<cfcontent type="image/x-ms-bmp" variable="#Picture.img#">

You can add to this also the mime from Database with CASE for GIF / JPG / PNG / BMP / TIFF as you like it. Smile

After that just call the page and you got it


<img src="picture.cfm?id=100" />

I think doing so I have solved more or less the 80% of the unsolved visualization problem Smile GATCHA!

Have a nice day.

Fabio Bandini
Crystal Design Studio
Via Gentili,41
47100 Forlì (FC)
Italy
Developer & Programs Analyst
ColdFusion & C# Very Happy Very Happy Very Happy

Edited 02/10/09 {ts '2018-09-20 09:10:00'}

New Topic Reply Subscription Options   Previous Page  Page: 1   Previous Page
Subscription Options
Subscription options are available after you log in.

There are 24 active user sessions right now.