2012-04-26 49 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