タイトルが少し変だとは思いますが、そこに着きます。
私はラップトップにつながれたカメラを持っています。リモート撮影を使用すると、写真家が写真を撮ると、ラップトップのハードドライブ上のフォルダーに保存されます。Automator(Mac OS X)アクションがフォルダーに設定されており、新しいファイルが表示されるたびに、ファイルのサイズが変更され、Transmitを使用してFTPにプッシュされます。
ここでコードが登場します。
最近撮影した写真を表示するWebページがあります。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);
そして、これがそのJavascriptで呼び出される2つのPHPファイルです
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;
これらはすべて、ほぼ完璧に機能します。問題は、ファイルがアップロードされている最中にループが発生した場合だと思います。時折写真が撮られ、ページの途中にしか表示されません。エラーはまったくスローされず、スクリプトは引き続き正常に実行され、画像ファイルは実際にその状態でキャッシュされます。これにより、コードが進行中のファイルアップロードをキャッチし、ファイルの一部のみを表示していると思います。その時点でアップロードされています。
この問題を克服するために必要な場合は、ソリューションを変更してもかまいません。正確に何をすべきかわからないだけです。
編集
以下の提案の1つに従って、getNewestPhoto.phpにコードを追加しました。このコードは、写真のファイルサイズをチェックし、少し待ってから、もう一度チェックします。それらが異なる場合は、ファイルサイズが同じになるまで戻って再度チェックします。ループ間でファイルサイズが変わるため、アップロードの途中のファイルをキャッチできると期待していましたが、写真が部分的にレンダリングされている場合でも、ファイルサイズチェックでキャッチされませんでした。
これが私が追加したコードです
$currFilesize = filesize($path . $mostRecent);
$newFilesize;
while ( true ) {
sleep(.5);
$newFilesize = filesize($path . $mostRecent);
if ( $newFilesize == $currFilesize) {
break;
}
else {
$currFilesize = $newFilesize;
}
}
私は(別の提案を介して)アップロード時にある種のロックファイルを追加する必要があると考えています。これにより、コードによる写真の更新が停止され、アップロードが完了すると削除されますが、どのような種類のWebも実行していないことがわかります。カメラに接続されたコンピューター上のサーバー、それを達成する方法がわかりません。提案が欲しいです。