2012-11-06 35 views
2

我有一個自動例程,可以由用戶觸發將圖像上傳到Amazon S3。用戶通常會有超過500個項目上傳,我正在努力尋找一種不會讓程序超時的方法。如何防止在Coldfusion中多文件上傳超時?

現在我這樣做:

<form action="hs_import.cfm?ansicht=Bilder&RequestTimeout=5000" method="post" name="uploader"> 
... 
    <input type="button" OnClick="bilder_upload()" value="#tx_gen_run#"> 
    <input type="hidden" name="artikel_uploaden" value="ja"> 
    <input type="hidden" name="ansicht" value="imageloader"> 
</form> 

觸發JavaScript函數,這將觸發我的上傳(沒有詳細說明):

<cfif isdefined("artikel_uploaden")> 
<cfscript> 
     S3 variables 
</cfscript> 

    <!--- get img paths to upload ---> 
    <cfquery datasource="db" name="img_paths"> 
    SELECT DISTINCT imgpath 
</cfquery> 

    <cfif img_paths.recordcount GT 0> 
     <cfloop query="img_paths"> 
      <cfif img_paths.typ NEQ "img"> 
       <cfset variables.testFilePath = img_paths.bildpfad & img_paths.bilddateiname> 
       <cfset variables.fileExt = ListLast(variables.testFilePath, ".")> 


       <!--- get image ---> 
       <cfhttp timeout="45" 
        throwonerror="no" 
        url="#variables.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="variables.objGet"> 

       <!--- validate ---> 
       <!--- upload 4 sizes (s,m,l,xl) to S3 --->   
       <cftry> 
        <cfset objImage = ImageNew(variables.objGet.FileContent)> 
        <cfimage source="#objImage#" action="write" quality=".99" destination="#variables.tempDirectory#_base_#img_paths.bilddateiname#" overwrite="yes"> 
        <cfset variables.basePath = variables.tempDirectory & "_base_" & img_paths.bilddateiname> 
        <cfimage action="read" source="#variables.basePath#" name="base"> 
        <cfset variables.imageSrc = variables.tempDirectory> 
        <cfscript> 
         if (ImageGetWidth(base) LT ImageGetHeight(base)) { 
         // portrait          
         } else { 
         // landscape/square 

         } 
         // cleanup 
        </cfscript> 

        <!--- create IMG entry in media table ---> 
        <cfquery datasource="db"></cfquery> 
       </cfif> 
      <cfcatch> 
       <cfset variables.errorCount = variables.errorCount+1> 
       <cfset variables.failedLoads = variables.failedLoads & img_paths.bilddateiname & " (" & tx_pop_error & ":" & tx_errors_import_ext & "), "> 
      </cfcatch> 
     </cftry> 
    </cfif> 
    </cfloop> 
    <!--- alert on success and errors ---> 
</cfif> 

這工作不錯,但瀏覽器只是掛起如果圖像數量過大,則會出現/超時,所以我通常會查看永不完成的加載屏幕,並且不會提示成功/錯誤。

問題
什麼將是處理大文件上傳這樣一個更好的選擇?例如,這是否應該進入cfschedule,以便它可以在後臺運行?

感謝的提示!

回答

0

您遍歷一個CFQUERY,這是非常糟糕的事情,並能造成重大怠工。解決這個問題的一個方法是將100個查詢存儲到一個變量中,然後立即運行多個查詢(它可能需要很長時間才能打開和關閉連接)。當我使用此樣式進行批量更新時,會得到性能提高了90%,速度更快。

這可能是足以讓你的工作流程。當然,如果你有很多真正的大圖像,沒有太多做有關(除限制圖像大小)

+0

hm。我喜歡這個主意。你能告訴我如何在一個變量中存儲「100個查詢」嗎?從來沒有這樣做過。 Thx到目前爲止。 – frequent

+0

@frequent:我從內存中完成這個工作(不再用CF編寫代碼),只是創建一個變量,並將查詢存儲在分隔符中,用分號分隔。然後每隔100個循環,將變量的值轉儲到cfquery中。我記得,你將需要使用PreserveSingleQuotes。 – Limey

2

你正在試圖做的非常多的在一個單一的請求。雖然一個或五個圖像可能不會生成超時,但肯定會有數百個消息。從你上面提供的代碼,你正在做在單個請求中執行以下操作:

  1. 上傳[n]的圖像
  2. 發出HTTP請求以獲取每個圖像
  3. 調整每個圖像(可能爲4個不同的尺寸,而不是完全從樣品全部清除)
  4. 上傳的每個操作的每個圖像的至S3

版本這是一個很大的工作,特別是考慮到這兩個CFHTTP,更具體地說,cfimage是不是最快標籤在語言中。通過cfimage進行圖像處理可能會很慢。

你可能好得多做你的建議:除了打破這些任務,做盡可能多的處理在後端使原有的客戶請求不等待。您可以進行初始圖片上傳,然後結束客戶請求,通知他們可能需要幾分鐘才能處理所有圖片。

你就必須使用計劃任務或任務隊列的選項(即;兔MQ)做圖像處理和上傳到S3。我甚至建議你有一個單獨的實例來處理預定的任務,以便在客戶直接與你的Web應用程序交互的實例中不處理這些處理工作。將圖像處理和S3上傳分解爲單獨的任務甚至可能會更好,因此您可以通過錯誤處理來捕獲圖像處理(即:錯誤的文件格式)問題,而無需再上傳S3上載過程。這需要在後端進行更多的跟蹤工作(即:哪些圖像仍然需要處理,哪些圖像仍然需要上傳到S3),但這並不難實現,併爲您提供了更加強大的工作流程設置。

+0

也謝謝。是的,我從上傳的圖片中創建了4種尺寸。我仍然不確定上傳圖片的最佳方式是什麼。我的過程正在發揮作用,但需要長時間(旁註:我已經放棄告訴用戶,5MB圖像不適合上傳或使用,並且很高興圖像位於正確的文件夾中;-)但是,我想我最終會移動過程轉換成'cfschedule'並在稍後運行。兔子MQ對此有好處嗎?我不確定的一件事是將其分解爲單獨的任務。如果我正在排班,我不妨運行整批。 – frequent

+0

Rabbit MQ是一個任務隊列。將任務放入隊列,跟蹤狀態以及在隊列完成時將其從隊列中刪除非常有用。如果你要創建一個真正分解的服務(即打破圖像驗證,調整大小,上傳到S3,並通知客戶進入單獨的服務),Rabbit MQ可能會幫助很多。你是對的:你可以將它作爲一個單獨的計劃任務來完成。將事情分開的好處在於,在需要時交換代碼很容易,而且更容易處理錯誤。 – Brian

0

如果您希望用戶觸發請求,您可以通過AJAX調用完成請求,而不是等待回覆。只需告訴用戶請求正在後臺運行。您還可以在完成頁面線程並顯示「請求正在處理」頁面時使用cfthread啓動大量請求。

Ask Ben: Processing Files With CFThread In ColdFusion