Use Content Length When Streaming Binary Variables In ColdFusion

Posted July 25, 2007 at 6:27 PM

Tags: ColdFusion

I was just reading over on cf.Objective() about how it's important to use Content-Length when streaming files to the client. Without it, the browser knows how much it has downloaded so far, but not necessarily how much it will have to download in total (I guess it goes till some sort of End Of File marker?). I can understand the need for this fix - there is perhaps nothing more frustrating than having no idea how much file you have left to download.

The problem is that while I sometimes stream actual files, it is more common that I stream binary data using ColdFusion CFContent's Variable attribute. Jared only covered the File attribute, so I wasn't sure what to do in this case. But after a bit of testing, it looks like the browser is happy know the number of bytes in the byte array that represents the binary object:

 Launch code in new window » Download code as text file »

  • <!--- Kill extra output. --->
  • <cfsilent>
  •  
  • <!--- Read in the image binary. --->
  • <cffile
  • action="readbinary"
  • file="#ExpandPath( './test_girl.jpg' )#"
  • variable="binImage"
  • />
  •  
  •  
  • <!---
  • Set the content disposition and give a suggested
  • file name for the client.
  • --->
  • <cfheader
  • name="content-disposition"
  • value="attachment; filename=test_girl.jpg"
  • />
  •  
  • <!---
  • Set the content length. This is the length of the
  • byte array that represenets the binary image object.
  • --->
  • <cfheader
  • name="content-length"
  • value="#ArrayLen( binImage )#"
  • />
  •  
  • <!---
  • Set the content type and then stream the binary
  • image to the client.
  • --->
  • <cfcontent
  • type="image/jpeg"
  • variable="#binImage#"
  • />
  •  
  • </cfsilent>

This downloads the file nicely, and when I check the headers in FireBug, the content length is set correctly. Thanks Jared, good tip.

Also, as a funny little thing, if I increase the content-length by doing something like this:

 Launch code in new window » Download code as text file »

  • #(ArrayLen( binImage ) + 1)#

... FireFox will actually never stop trying to download the image! I guess it just won't give up hope on that last byte :) So, I guess the moral of the story is that if you are going to provide a content length to the browser, make sure that it is correct otherwise you will do more damage than good.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page





Reader Comments

Jul 25, 2007 at 8:27 PM // reply »
32 Comments

Cool tip! I'll definitely remember this when I start working on an app in a few weeks that will be uploading/downloading files.

CooLJJ


Jul 25, 2007 at 9:25 PM // reply »
1 Comments

Cool. I will be using that at work tomorrow.


Aug 1, 2007 at 5:48 PM // reply »
18 Comments

Ben,

This is good, but not perfect. Docs say:

"Note: This action reads the file into a variable in the local Variables scope. It is not intended for use with large files, such as logs, because they can bring down the server."

What if you allow users/customers to download files routinely in the megs.

I haven't found a good solution to be able to give the file size for large files. Any ideas?


Aug 2, 2007 at 7:43 AM // reply »
7,572 Comments

@Sami,

To be honest, I don't deal with a lot of file security most of the time. Therefore, I usually just link to files directly on the public server which bypasses all the ColdFusion stuff and just lets IIS deal with the file transfer.

But I agree with the documentation - this is not a good idea for large files. If you need file security, I guess the best thing to do is copy the file to a temp directory and then forward the person to it.


Aug 2, 2007 at 6:38 PM // reply »
18 Comments

This would be a good test:

Compare CF's native approach to using the java.io class, across multiple file sizes.

http://www.exampledepot.com/egs/java.io/GetLength.html

Sami


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »
Jim
Mar 19, 2010 at 4:49 PM
Nobody Puts Baby In The Corner!
Wow. This is like suddenly finding a support group for your secret shame. I'm not alone! I always liked this movie, even though it is extremely cheesy. I just wish Jennifer Grey hadn't gotten the ... read »
Mar 19, 2010 at 4:47 PM
Application.cfc OnRequest() Method Affects OnError() Arguments
@Jason and @Ben, I've been doing some CF9 refactoring on our systems and noticed an odd occurrence with onError as well. Found a way to work around my problem, but what I saw was... Background: Our ... read »
Jim
Mar 19, 2010 at 4:44 PM
Shoot 'Em Up Starring Clive Owen And Paul Giamatti
I actually enjoyed this movie quite a lot. It was different, certainly, but I think they were going for more of a Quentin Tarentino-"wow, that was weird"-vibe than an actual spoof. Once I realize ... read »
Mar 19, 2010 at 4:34 PM
An Intensive Exploration Of jQuery With Ben Nadel (Video Presentation)
Hey I guess the video is down. Is there anyway you can upload to youtube or vimeo or some other service? Greatly appreciated. ... read »
Mar 19, 2010 at 4:24 PM
ColdFusion CFPOP - My First Look
@Ben Thanks for the follow up! The root of the problem had to do with being able to trace bounced emails to specific records in a DB table. Let's say you run an email campaign and you get 1,000 bou ... read »
Mar 19, 2010 at 4:15 PM
SQL COUNT( NULLIF( .. ) ) Is Totally Awesome
Thank you Ben and Tony! Either of these work for the summary report I am working on and the info is much appreciated! I think I like Tony's a little better because I won't have to educate every ... read »
Mar 19, 2010 at 3:35 PM
ColdFusion Path Usage And Manipulation Overview
@Ben, Sorry. Clarification. expandpath worked for me in application.cfc, but not in other templates. ... read »