是否可以使用Coldfusions cfthread延迟加载图像?

时间:2012-08-25 22:01:44

标签: image-processing coldfusion lazy-loading cfthread

我正在运行coldfusion8/MySQL5.0.88并且我有一个产品搜索,我需要在显示它们之前拉入并调整来自各种外部来源的图像。

虽然我可以在创建产品时(主要是搜索产品)进行此操作,但我无法确保所有图像都可以通过我的服务器以调整大小的格式显示,因此我需要在产品搜索中进行某种回退。

现在,我正在检查图像是否在服务器上可用,如果没有,我会触发一个例程来抓取并调整图像大小如下:

// check if image is available
<cfif results.typ NEQ "img" AND results.typ NEQ "alt">
    <cfif results.bildpfad neq "" AND results.bilddateiname neq "">
    <cfset imgSuccess = form_img_handler.upload
        ( command   = "upload_search"
        , imgPath   = results.bildpfad
        , imgFile   = results.bilddateiname
        , sellerILN = results.iln
        , cookie    = variables.screenWidth
        )/>
    <cfif imgSuccess EQ "false">
        <cfset variables.imgFail = "true">
    </cfif>
 </cfelse>
     <cfset variables.imgFail = "true">
 </cfif>

// missing img
<cfif variables.imgFail EQ "true">
    <cfoutput><div class="resultsImgWrap noImgFound"></div></cfoutput> 
    <cfset variables.imgFail = "false">
<cfelse>
// show image
    <cfoutput><div class="resultsImgWrap"><img src="#variables.imageSrc#" /></div></cfoutput>
</cfif>

upload函数处理cfhttp请求并调整大小并返回true/false

我想知道是否可以在此上下文中使用cfthread,因此当用户进行搜索时,我会输出包含正确URL链接的标记,但是图像拉/调整大小/保存到目标将在cfthread中完成,以加快为用户显示结果。

问题
一旦cfthread完成处理,图像是否会显示;或者在尝试加载尚未创建的图像时(这可能),此方法是否会产生404错误?有没有其他方法向用户展示某些内容并让用户在上传和处理图片时继续使用?

感谢您的投入!

修改
好。根据答案,我想出了以下内容。虽然还没有工作,但我认为它朝着正确的方向发展。

// check media log, if image is logged (already created), if so, load it, if not pull it from external
<cfif results.typ NEQ "img" AND results.typ NEQ "alt">
    // check path and filename
    <cfif results.bildpfad neq "" AND results.bilddateiname neq "">
        // pull in
        // arguments: 
        // cm = form
        // pt = path to image
        // fl = filename
        // se = seller id  
        // ck = screen width (I'm using adaptive image sizes
        // ax = origin
        // gb = which image size to return
        <cfset variables.imgSrc = expandPath("../services/img_handler.cfc") & "?method=up&cm=results&pt=" & results.bildpfad & "&fl=" & results.bilddateiname & "&se=" & results.id & "&ck=" & variables.screenWidth & "&ax=rm&gb=s">
    <cfelse>
        cfset variables.imgFail = "true">
    </cfif>
</cfif>

<cfif variables.imgFail EQ "true">
    <cfoutput><div class="resultsImgWrap noImgFound"><img src="../images/not_found.png"></div></cfoutput>
    <cfset variables.imgFail = "false">
 <cfelse>
    <cfoutput><div class="resultsImgWrap"><a class="swipeMe" rel="external" href="#variables.zoomSrc#">
                <img src="#variables.imageSrc#" class="adaptImg ui-li-thumb" /></a>
              </div></cfoutput>
</cfif>

因此,这将检查我正在查询的媒体日志中的图像以及结果(避免对现有图像进行不必要的s3检查)。如果日志中没有图像,我正在检查路径/文件名是否为空并触发我的intelligent图像加载器,它执行以下操作:

<cfcomponent output="false" hint="image handler">
    <cffunction name="Init" access="public" returntype="any" output="false" hint="Initialize">
        <cfreturn true />
    </cffunction>       

    <cffunction name="upload" access="remote" output="false" hint="creates images and stores them to S3">
        <cfargument name="cm" type="string" required="true" hint="" /> 
        <cfargument name="pt" type="string" required="true" hint="" /> 
        <cfargument name="fl" type="string" required="true" hint="" />
        <cfargument name="se" type="string" required="true" hint="" />
        <cfargument name="ck" type="string" required="true" hint="" />
        <cfargument name="gb" type="string" required="false" hint="" />
        <cfargument name="ax" type="string" required="false" hint="" />

        <cfscript>  
           var LOCAL = {};  
           // arguments
           LOCAL.command = cm;
           LOCAL.imgPath = pt;
           LOCAL.imgFile = fl;
           LOCAL.sellerILN = se;
           LOCAL.cookie = LSParseNumber(ck);
           LOCAL.getBack = gb;
           LOCAL.access = ax;
           // s3
           // commander
           if ( LOCAL.command NEQ "" ) {
                LOCAL.action = LOCAL.command;
           } else {
                LOCAL.action = "upload";
                }
           // s3 misc
           LOCAL.bucketPath = Session.bucketPath;
           LOCAL.bucketName = Session.bucketName;
           LOCAL.acl = "public-read";
           LOCAL.storage = "";
           LOCAL.tempDirectory = expandPath( "../members/img/secure/" );
           LOCAL.allow = "png,jpg,jpeg";
           LOCAL.failedLoads = "";
           LOCAL.altFailedLoads = "";
           LOCAL.createBucket = "false";
           LOCAL.errorCount = 0;
           LOCAL.altErrorCount = 0;
           LOCAL.cacheControl = 1;
           LOCAL.contentType = "image";
           LOCAL.httptimeout = "300";
           LOCAL.cacheDays = "30";
           LOCAL.storageClass = "REDUCED_REDUNDANCY";
           LOCAL.keyName = "";
           LOCAL.baseUrl = "http://www.baseurl.com";
           LOCAL.imageSrc = "";
           LOCAL.testFilePath = LOCAL.imgPath & LOCAL.imgFile;
           LOCAL.fileExt = ListLast(LOCAL.testFilePath, ".");
           LOCAL.runner = "s,m,l,xl";
           LOCAL.worked = "true";
      </cfscript>   
      // runner is the file size setter, in results I only create two sizes, during imports I create all four
      <cftry>
        <cfhttp timeout="45" 
            throwonerror="no" 
            url="#LOCAL.testFilePath#" 
            method="get" 
            useragent="Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12" 
            getasbinary="yes" 
            result="objGet">
        <cfscript>
            // set file sizes to create
            if ( LOCAL.command EQ "upload_search" ){
                if ( LOCAL.cookie LT 320 ) {
                    LOCAL.runner = "l,s";
                    }
                else if ( LOCAL.cookie GTE 320 AND LOCAL.cookie LTE 767 ) {
                    LOCAL.runner = "l,m";
                    }
                else if ( LOCAL.cookie GT 768 ) {
                    LOCAL.runner = "xl,m";
                    }
                else if ( LOCAL.cookie GT 1280 ){
                    LOCAL.runner = "xl,l";
                    }
                } else if ( LOCAL.command EQ "upload_import") {
                    LOCAL.runner = "xl,l,m,s";
                    }
            // validate
            if ( len(objGet.Filecontent) EQ 0 OR objGet.Mimetype EQ "text/html"  ){
                LOCAL.worked = "false length or mime";
                } else if ( NOT listfindnocase(LOCAL.allow, LOCAL.fileExt ) ){
                LOCAL.worked = "false wrong extension";
                } else {
                // create temp
                LOCAL.objImage = ImageNew(objGet.FileContent);
                LOCAL.basePath = LOCAL.tempDirectory & "_base_" & LOCAL.imgFile;
                imageWrite( LOCAL.objImage, LOCAL.basePath, ".99");
                LOCAL.base = imageRead( LOCAL.basePath );
                LOCAL.imageSrc = LOCAL.tempDirectory;

                // formats
                // S = 100x127, 
                // M = 180x230, 
                // L = 290x370, 
                // XL = 870x1110 

                // portrait
                if ( ImageGetWidth( LOCAL.base ) LT ImageGetHeight( LOCAL.base ) ){
                    for (LOCAL.i = 1; LOCAL.i LTE ListLen(LOCAL.runner,","); LOCAL.i = LOCAL.i+1){
                        LOCAL.lt = ListGetAt(LOCAL.runner, LOCAL.i, ",");
                        LOCAL.base = imageRead( LOCAL.basePath );
                        ImageSetAntialiasing(LOCAL.base,"on");
                        // default image width/height
                        LOCAL.height = Application.strConfig.respH[LOCAL.lt];
                        LOCAL.width = "";
                        ImageScaleToFit(LOCAL.base, LOCAL.width, LOCAL.height, "highestQuality");

                        LOCAL.filekey = LOCAL.lt & "_" & LOCAL.imgFile;
                        LOCAL.keyName = LOCAL.sellerILN & "/" & LOCAL.filekey;
                        LOCAL.filename = LOCAL.tempDirectory & LOCAL.filekey;
                        imageWrite( LOCAL.base, LOCAL.filename, ".99" );

                        // s3
                        Application.strObjs.s3.putObject(LOCAL.bucketName, LOCAL.filekey, LOCAL.contentType, LOCAL.httptimeout, LOCAL.cacheControl, LOCAL.cacheDays, LOCAL.acl, LOCAL.storageClass, LOCAL.keyName, LOCAL.imageSrc, "false" );
                        fileDelete( LOCAL.tempDirectory & LOCAL.lt & "_" & LOCAL.imgFile );
                        }
                    } else {
                    // same for landscape
                    ...
                    }
                }
                // cleanup
                fileDelete( LOCAL.tempDirectory & "_base_" & LOCAL.imgFile );
            } 
        </cfscript>
    // update media log
        ...
        <cfcatch>
        // dump errror message
        </cfcatch>
        </cftry>

    // return image 
        <cfif LOCAL.access EQ "rm">
            <cftry>
            <cfscript>
            if ( LOCAL.getBack EQ "s" ){
                LOCAL.passPath = Session.bucketPath & Session.bucketName & "/" & LOCAL.sellerILN & "/" & ListGetAt(LOCAL.runner, Listlen(LOCAL.runner), ",") & "_" & LOCAL.imgFile;
            } else if( LOCAL.getBack EQ "l" ) {
                LOCAL.passPath = Session.bucketPath & Session.bucketName & "/" & LOCAL.sellerILN & "/" & ListGetAt(LOCAL.runner, 1, ",") & "_" & LOCAL.imgFile;
            }
            LOCAL.mime = "image/" & LOCAL.fileExt;
            </cfscript>

            <cfcontent type="#LOCAL.mime#" file="#LOCAL.passPath#" />
            <cfcatch>
            // dump errors
            </cfcatch>                              
        </cftry>
    <cfelse>
        <cfreturn LOCAL.worked>
    </cfif>
    </cffunction>
</cfcomponent>

所以我正在设置我要创建的文件大小LOCAL.runner,并查看此列表,创建将基本图像调整为我的预设图像尺寸并将创建的图像存储在s3上。

问题cfcontent尝试在创建之前返回图像。当我运行代码时,我收到The file specified in contentTag does not exist错误。如果我检查S3,图像就在那里,所以我假设这是一个计时问题。

感谢关于如何强制'cfcontent'等到图像创建之后的任何指示!

1 个答案:

答案 0 :(得分:1)

输出到加载img的本地​​CFM的链接怎么样?我的意思是 - 对于服务器上存在的图像,您输出指向它的<img>标记。对于需要加载的图像,可以输出如下内容:

<img src="imagegetter.cfm?p=#urlofimagetoload#">

imagegetter.cfm将负责执行http以在本地获取图像并调整其大小。然后它可以通过cfcontent提供位。