2012-04-26 45 views
5

我知道這個標題有點奇怪,但我會到達那裏。在使用ajax和PHP獲取最新文件時避免部分上傳文件(通過FTP)

我有一臺相機連接到筆記本電腦。使用遙控拍攝,當攝影師拍攝照片時,將其保存到筆記本電腦硬盤上的文件夾中。在文件夾上設置了一個Automator(Mac OS X)操作,無論何時出現新文件,它都會調整其大小並使用傳輸將其上傳到FTP。

這裏就是代碼進來。

我有顯示拍攝的最新照片的網頁。它使用ajax重複檢查是否上傳了新文件,如果有,請加載新照片並用舊照片交叉淡入淡出。這是在頁面上運行的Javascript。

(function() { 
    var delay, refreshLoop; 

    // Alias to setTimeout that reverses the parameters, making it much cleaner in code (for CoffeeScript) 
    delay = function(time, callback) { 
    return setTimeout(callback, time); 
    }; 

    // Function that drives the loop of refreshing photos 
    refreshLoop = function(currentFolderState, refreshRate) { 
    // Get the new folder state 
    $.get("ajax/getFolderState.php", function(newFolderState) { 
     // If the new folder state is different 
     if (newFolderState !== currentFolderState) { 
     // Get the newest photo 
     $.get("ajax/getNewestPhoto.php", function(photoFilename) { 
      var img; 
      // Create the new image element 
      img = $('<img class="new-photo"/>') 
      // Append the src attribute to it after so it can BG load 
      .attr('src', "/events/mindsmack/booth/cinco-de-mindsmack-2012/" + photoFilename) 
      // When the image is loaded 
      .load(function() { 
       // Append the image to the photos container 
       $('#photos').append(img); 
       // Crossfade it with the old photo 
       $('#photos .current-photo').fadeOut(); 
       $('#photos .new-photo').fadeIn().removeClass("new-photo").addClass("current-photo"); 
      }); 
     }); 
     } 
     // Wait for the refresh rate and then repeat 
     delay(refreshRate, function() { 
     refreshLoop(newFolderState, refreshRate); 
     }); 
    }); 
    }; 

    // Document Ready 
    $(function() { 
    var refreshRate; 

    // Load the first photo 
    $.get("ajax/getNewestPhoto.php", function(photoFilename) { 
     $('#photos').append("<img src='/events/mindsmack/booth/cinco-de-mindsmack-2012/" + photoFilename + "' class='current-photo' />"); 
    }); 
    refreshRate = 2000; 
    // After the timeout 
    delay(refreshRate, function() { 
     // Get the initial folder state and kick off the loop 
     $.get("ajax/getFolderState.php", function(initialFolderState) { 
     refreshLoop(initialFolderState, refreshRate); 
     }); 
    }); 
    }); 

}).call(this); 

這裏是兩個PHP文件被稱爲在使用Javascript

getFolderState.php

<?php 

    $path = $_SERVER['DOCUMENT_ROOT'] . "/events/mindsmack/booth/cinco-de-mindsmack-2012/"; 

    // Get a directory listing of the path where the photos are stored 
    $dirListing = scandir($path); 

    // Echo an md5 hash of the directory listing 
    echo md5(serialize($dirListing)); 

getNewestPhoto.php

<?php 

    $path = $_SERVER['DOCUMENT_ROOT'] . "/events/mindsmack/booth/cinco-de-mindsmack-2012/"; 

    // Get a directory listing of the path where the photos are stored 
    $listing = scandir($path); 

    $modTime = 0; 
    $mostRecent = ""; 

    // Find the most recent file 
    foreach ($listing as $file) { 
     if (is_file($path.$file) && $file !== ".DS_Store" && filectime($path.$file) > $modTime) { 
      $modTime = filectime($path.$file); 
      $mostRecent = $file; 
     } 
    } 

    // Echo the most recent filename 
    echo $mostRecent; 

所有這些作品大多完美。我相信問題是當文件處於上傳過程中時,循環被觸發。偶爾會拍攝一張照片,它只會在頁面中間顯示。一個錯誤不會被拋出,腳本繼續運行得很好,並且圖像文件實際上被緩存在該狀態中,這導致我相信我的代碼正在捕獲正在進行的文件上載,並且只顯示文件的一部分那個時候已經上傳了。

我不介意改變我的解決方案,如果我需要爲了克服這個問題,我只是不知道該怎麼做。

編輯

一種按照下面的建議之一,我再次添加代碼,以我的getNewestPhoto.php,檢查照片的文件大小,等待了一下,並檢查它。如果它們不同,則返回並再次檢查,直到文件大小相同。我希望這可以捕獲上傳的文件,因爲文件大小會在循環之間變化,但即使照片部分渲染,文件大小檢查也無法捕捉到。

這是我加入

$currFilesize = filesize($path . $mostRecent); 
$newFilesize; 

while (true) { 
    sleep(.5); 
    $newFilesize = filesize($path . $mostRecent); 

    if ($newFilesize == $currFilesize) { 
     break; 
    } 
    else { 
     $currFilesize = $newFilesize; 
    } 
} 

我想(通過另一個建議),我需要添加某種對上傳鎖定的文件,它從清涼的照片停止碼,並且當移除代碼上傳完成,但看到我沒有在連接到相機的計算機上運行任何類型的Web服務器,我不知道如何實現這一點。我很樂意提出建議。

+1

除非您可以在上傳時存儲「鎖定」文件或其他東西,否則PHP將如何知道您正處於傳輸過程中?可能是最簡單的解決方案。上傳一個'filename.lck'並在包含它之前檢查它。然後在完成傳輸後刪除鎖。 – MetalFrog 2012-04-26 19:16:19

+0

這聽起來像是一個非常棒的解決方案,但我不確定如何去做,因爲在文件上傳中沒有涉及到實際的代碼。 – 2012-04-26 19:19:55

+0

是的,我對Automator一無所知,只是想把想法拋出去。希望我能有更多的幫助。 – MetalFrog 2012-04-26 19:21:46

回答

3

有很多途徑可以解決這個問題,比我所建議的要好得多。然而,我認爲最簡單和最快捷的解決方案是將FTP傳輸到tmp目錄,並在傳輸完成時觸發文件移動到生產目錄。你的本地自動化工作是否有這樣一種機制來處理傳輸?

+0

難道這不可能會遇到同樣的問題,只是在服務器上的文件夾之間移動照片,而不是首先上傳它們? – 2012-04-26 19:22:03

+0

我不這麼認爲。此舉幾乎是即時的。 – JAAulde 2012-04-26 19:40:57

+0

我不相信我有一種機制,可以使用Automator在遠程服務器上移動文件,只上傳它們。你能想出另一種方法來實現這一點嗎?也許如果我將服務器安裝成驅動器,而不是通過FTP上傳,我可以在其上移動文件? – 2012-04-26 20:26:41

1

我會讓PHP腳本檢查一個循環中的文件大小(小)延遲,如果它匹配,然後輸出文件。否則,循環直到它結束。

+0

PHP代碼並不知道_incoming_圖片應該有多大... – JAAulde 2012-04-26 19:18:20

+1

您可以讓automator腳本先檢查文件名,然後將THAT作爲小文本文件,並讓PHP腳本檢查並匹配它。 或者,只需檢查循環的兩次迭代之間的文件差異。 – gcochard 2012-04-26 19:19:15

+0

沒錯,那是一個選項。 – JAAulde 2012-04-26 19:19:46