【问题标题】:Is it possible to lazyload images using Coldfusions cfthread?是否可以使用 Coldfusions cfthread 延迟加载图像?
【发布时间】:2012-09-01 05:56:23
【问题描述】:

我正在运行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”等到创建图像的指示!

【问题讨论】:

    标签: image-processing coldfusion lazy-loading cfthread


    【解决方案1】:

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

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

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

    【讨论】:

    • 好的。找到this :-) 还有一个问题:我将上面的内容与photoswipe 一起使用,这需要设置一个URL,如果激活photoswipe,将从该URL 加载图像。如果我通过imagegetter.cfm 运行丢失的图像,我在发回图像时也会有一个有效的路径。知道如何用新路径替换imageGetter.cfm?... url吗?如果我离开路径,photoswipe 将在激活时重新请求 imagegetter.cfm。
    • 如果 imagegetter.cfm 是“智能的”(即,它知道何时下载/调整大小),那么您是否使用该 URL 也没关系。对吗?
    • 坐在上面,让它变得智能:-)。此外,由于我使用的是自适应尺寸(= s、m、l、xl),我正在使用 imagegetter 显示小版本,并输出一个用于照片滑动到大版本的常规链接,这应该在用户触发时完成照片滑动。仍在测试中,一旦我完成所有工作,我将发布解决方案。到目前为止再次感谢!
    • 好的。我让它有点工作,我的 CfC 类似于某种智能......见我上面的编辑。我的最后一个问题是cfcontent 尝试在图像仍在创建时返回图像 - 我得到了一个详细信息:s3.amazonaws.com/folder/img_file.jpg` 未找到消息,尽管当我检查存储桶时,图像就在那里。从我的代码中知道什么可能是错的?
    猜你喜欢
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 2018-02-15
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多