Hello again. I was wondering if you might have any idea on how to figure this out. I am trying to capture images with <cfimage> that use a redirect of some kind. Here's the situation... CafePress.com has an affiliate web service. In their returned XML, the image location is something like this:
http://www.cafepress.com/cp/search/image.aspx?p=57077504&i=8382663
I can't get an image name to capture using the above url so I can call the image later locally off of my server. What is interesting is that if you cut/paste the above url into your browser, you are redirected to:
http://images.cafepress.com/product/57077504v5_150x150_Front.jpg
Obviously, here, I can use listlast(url, "/") to get an image name. Any ideas on how to transform the first URL into the second URL on the fly?
By default, ColdFusion's CFHttp tag follows redirects that are returned in the response headers. This turns out to be something easy to stop. All you have to do is set the Redirect attribute of the CFHttp tag to False. By doing this, ColdFusion will just return the CFHttp response to the invoking code no matter what data it has in it.
To see what I am saying, let's try calling the above URL using the standard, default ColdFusion CFHttp tag:
Launch code in new window » Download code as text file »
Notice here that we are not doing anything special except using the HEAD method instead of the GET method. This makes the same request, but instead of downloading the entire contents of the response body, this request just waits for the response headers to be sent. This gives us all the information we are looking for and takes a fraction of the time to execute (less data to transfer). Running the above code, we get the following CFDump output:
| | | | ||
| | ![]() | | ||
| | | |
Notice that the returned content type is an image and that the status code is 200. This is because ColdFusion followed the redirect returned from initial Cafe Press request.
Now, let's run the same code, except this time, we are going to tell the ColdFusion CFHttp request not to follow any redirects by setting the Redirect attribute to false:
Launch code in new window » Download code as text file »
Running this updated code, we get the following CFDump output:
| | | | ||
| | ![]() | | ||
| | | |
Notice that this time the response code was 302 - Moved Temporarily. ColdFusion did NOT follow this redirect to the target image. Notice also that this time, there is a Location key in our response header. This is the file to which ColdFusion was being redirected. Knowing this, we can then grab that Location URL and make a subsequent ColdFusion CFHttp call to download the image binary:
Launch code in new window » Download code as text file »
Here, we are getting the response headers without following redirects. We then grab that returned target Location and launch a second ColdFusion CFHttp call which downloads the target image as a binary object. This binary object is then being streamed to the browser:
| | | | ||
| | ![]() | | ||
| | | |
Instead of streaming it to the browser, you could have just as easily done a ColdFusion CFFile write to store it on the server's file system.
Hope that helps a bit.
Download Code Snippet ZIP File
Comments (7) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
First of all, thanks! A few questions about your code...
#1. Why do you "break up" the strBaseUrl into 2 sections? For visual reasons?
#2. How is
<cfset strFileName = ListLast(objGet.ResponseHeader.Location,"/\") />
different than
<cfset strFileName = ListLast(objGet.ResponseHeader.Location,"/") /> for getting the filename?
#3. What are you "cleaning up" with: <cfset strFileName = strFileName.ReplaceAll("[^\w\d\.\-_]+","_") />? RegEx is like reading Sanskrit to me. :)
Posted by J on Aug 31, 2007 at 8:52 AM
@J,
#1: Yes, purely for visual reasons. I try to keep my lines less than 65 characters long otherwise it might make my CODE div scroll horizontally, and this can be hard to read (for me), especially if the horizontal scroll bar takes vertical scrolling to get to.
#2: The difference is only that I am using both forward and backward slashes as list delimiters. Most likely, yours is just fine. I get nervous about the paths. I am never 100% sure which slash gets used, so just as a precaution, I use both as list delimiters. I know that on Windows vs. Linux the file system slashes are different (I think), but I don't know about web paths - I guess those are always forward slashes right? I'm just nervous, and I take a bit of precautions.
#3: The regex there is using the underlying Java regex engine, but this could also be written more safely as:
<cfset strFileName = REReplace(
strFileName,
"[^\w\d\.\-_]+",
"_",
"ALL"
) />
As far as what it is doing, it is replacing all characters that are NOT word, digit (hmmm, included in word in think, oops), ., -, or _ with the underscore. Basically, it is leaving you with just character-based file names (no spaces and random punctuation and what not).
Posted by Ben Nadel on Aug 31, 2007 at 9:01 AM
@J,
As far as #3 is concerned, you don't really have to do it. It's just a precaution to make sure the file name isn't crazy.
Posted by Ben Nadel on Aug 31, 2007 at 9:02 AM
Good tip as always. Thanks Ben.
Posted by Boyan on Aug 31, 2007 at 9:32 AM
Ben, I am new to using and authoring ColdFusion and I am attempting to redirect all requests from http://www.edwardbeckett.com/index.cfm to http://www.edwardbeckett.com/ The script I'm using works for any non- www. requests to the domain. However, It does not work for the index.cfm file. Can you take a look at this and tell me what looks wrong? Thanks, Edward Beckett
~Application.cfm~
<cfif left(CGI.HTTP_HOST,4) NEQ 'www.'>
<cfif CGI.Path_info EQ '/index.cfm'>
<cflocation url="http://www.#CGI.HTTP_HOST#/" addtoken="no">
<cflocation url="http://#CGI.HTTP_HOST##CGI.Path_Info#" addtoken="no">
</cfif>
</cfif>
Posted by Edward Beckett on Oct 29, 2007 at 9:12 PM
@Edward,
You have two CFLocations in a row. This does not work this way. The first CFLocation will execute and then basically abort out of the page processing such that the second one never gets run.
I don't think you even need that inner CFIF. Just execute the CFLocation that include the Path_Info all the time. There is no need to not have it. On requests that don't have a path, at the very worst, CGI will return the empty string, which is the same as running the first CFLocation that doesn't have path_info.
Posted by Ben Nadel on Oct 30, 2007 at 7:27 AM
i was just looking for this kind of tips, well thanks
Posted by marc on Dec 2, 2007 at 12:12 PM