2012-04-01 7 views
29

Есть ли способ проверить, был ли файл полностью загружен на сервере? Мой сценарий: Пользователь загружает файл поверх ftp, а другая моя задача PHP работает в cronjob. Теперь я хотел бы проверить, был ли файл загружен или пользователь по-прежнему загружается. Это важно, потому что тогда я знаю, могу ли я работать с этим файлом или ждать, пока он будет загружен. Спасибо.php, как проверить, был ли файл полностью загружен

+0

Какой у вас FTP-сервер? – galymzhan

+1

Существует, конечно, нетривиальный способ реализовать это с помощью php. Если информация о загружаемом файле не известна (например, хеш-сумма) заранее, нет способа определить, завершена ли передача файла или все еще выполняется или может быть прервана, без анализа самого процесса службы ftp , Вам нужно будет связаться с ftp-службой и посмотреть, может ли она предоставлять информацию для требований. – thrau

+2

Возможный дубликат [PHP: Как избежать чтения частичных файлов, которые были перенесены мне с FTP?] (Http://stackoverflow.com/questions/5826890/php-how-do-i-avoid-reading-partial- files-that-are-push-to-me-with-ftp) Это может помочь –

ответ

-6
<?php 
    if (move_uploaded_file($_FILES["uploader_name"]["tmp_name"], $path_name)): 
     //print true condition 
    else: 
     //print false condition 
    endif; 
?> 
+11

За FTP он сказал – Hubro

4

Возможным решением было бы проверить размер файла каждые несколько секунд, используя петлю, и если размер такой же, между двумя петлями предположить, что это загружено.

что-то вроде:

$filesize = array(); 
    $i = 0; 
    while(file_exists('/myfile.ext')) { 
    $i++; 

    $filesize[$i] = filesize('/myfile.ext'); 

    if($filesize[$i - 1] == $filesize[$i]) { 
    exit('Uploaded'); 
    } 

sleep(5); 

} 
+2

Это все еще просто предположение. Существует множество ситуаций, когда размер файла останется неизменным между двумя такими интервалами. – Hubro

20

У меня был один и тот же сценарий и нашел быстрое решение, которое работало для меня:

Пока файл загрузки через FTP, значение filemtime($yourfile) непрерывно модифицированную. Когда time() minus filemtime($yourfile) больше, чем X, загрузка прекратилась. В моем сценарии 30 было хорошим значением для x, вы можете использовать любое другое значение, но оно должно быть полезным как минимум 3.

Я знаю, что этот метод не гарантирует целостность файла, но, поскольку никто, кроме меня, не собирается загружать, я смею предположить это.

30

Если у вас есть контроль над приложением, выполняющим загрузку, вы можете потребовать, чтобы он загрузил файл в name.tmp, и когда он будет загружен, переименуйте его в name.final. Ваш PHP-скрипт может выглядеть только для имен *.final.

+0

+1 Я бы решил это так же. – Zaffy

+0

не самый лучший способ, но он будет работать – Shaheer

+0

вид бесполезного ответа. Очевидно, что это был бы первый вариант во многих случаях, я уверен, что OP думал об этом b4, спрашивая Q. Но что, если у вас нет доступа к настройкам ftp-сервера или, возможно, вы не хотите добавлять другую зависимость в вашем приложении (настройки ftp) – Alex

14

если вы работаете PHP на Linux, то Lsof может помочь вам

$output = array(); 
exec("lsof | grep file/path/and/name.ext",$output); 
if (count($output)) { 
    echo 'file in use'; 
} else { 
    echo 'file is ready'; 
} 

EDIT: в случае выдачи разрешения. используя методы sudo или suid, php-скрипт может получить требуемые разрешения для выполнения команды lsof. чтобы установить suid, вы должны ввести следующую команду как root.

su root 
chmod u+s /usr/sbin/lsof 
+0

Это не работает. Я вижу процессы, которые используют этот файл, когда я запускаю команду в консоли linux, но когда я запускаю команду с помощью PHP exec, ничего не возвращается. Возможно, потому что PHP не имеет прав на просмотр процессов, которые используют файл? – Alex

+0

вы можете использовать suid для переопределения проблемы разрешения – nasirbest

+2

См. Http: // stackoverflow.com/a/2527080/1488762 для более эффективного использования 'lsof', в результате чего:' exec ("lsof $ filename>/dev/null", $ dummy, $ status); if (! $ status) {/ * in use * /} ' –

10

Существует множество различных способов решения этой проблемы. Просто назовите несколько:

  1. Используйте signal file, который создается перед отправкой и удалением по завершении.
  2. Узнайте, есть ли у вашего FTP serverconfiguration option, который, например, дает незавершенным файлам расширение «.part» или блокирует файл на уровне файловой системы (например, vsftp).
  3. Получить список всех открытых в данный момент файлов в этом каталоге, проанализировав вывод команды UNIX/Linux lsof и проверьте, находится ли файл, который вы проверяете, в этом списке (примите во внимание комментарий Насира, если вы сталкиваетесь с разрешением проблемы).
  4. Проверьте, является ли файл last modification этого файла более длинным, чем определенный порог.

Как представляется, ваши пользователи могут использовать любой FTP-клиент, которого они хотят, первый метод (файл сигнала) не может быть использован. Второй и третий ответы требуют более глубокого понимания UNIX/Linux и зависят от системы.

Так что я думаю, что method #4 - это способ пойти в PHP до тех пор, пока латентность обработки (в зависимости от настроенного порога) не проблема. Он прост и не зависит от каких-либо внешних команд:

// Threshold in seconds at which uploads are considered to be done. 
$threshold = 300; 

// Using the recursive iterator lets us check subdirectories too 
// (as this is FTP anything is possible). Its also quite fast even for 
// big directories. 
$it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($uploadDir); 

while($it->valid()) { 
    // Ignore ".", ".." and other directories. Just recursively check all files. 
    if (!$it->isDot() && !$it->isDir()) { 
    // $it->key() is the current file name we are checking. 
    // Just check if it's last modification was more than $threshold seconds ago. 
    if (time() - filemtime($it->key() > $threshold)) { 
     printf("Upload of file \"%s\" finished\n", $it->key()); 

     // Your processing goes here... 

     // Don't forget to move the file out so that it's not identified as 
     // just being completed everytime this script runs. You might also mark 
     // it in any way you like as being complete if you don't want to move it. 
    } 
    } 
    $it->next(); 
} 

Я надеюсь, что это поможет любому, у кого есть эта проблема.


Похожие вопросы:

Verify whether ftp is complete or not?

PHP: How do I avoid reading partial files that are pushed to me with FTP?

+0

lsof не работает в PHP, см. мой комментарий выше :) – Alex

+0

@Alex Спасибо, я не знал об этом и не обновлял свой ответ. Но, как указал Насир, это вопрос разрешений и может быть исправлен. В конце концов, это только укрепляет меня, на мой взгляд, что метод №4 является самым простым способом :) – flu

-1

Проверка файла после загрузки с помощью следующего кода

if (file_exists('http://www.domain.com/images/'.$filename)) : 

    // Write some response as you like as a success message 

endif; 

Примечание: вы должны изменить путь изображения по твоим ,

удача :)

+1

используйте «\' »для обозначения кода - то есть' if (file_exists ('http://www.domain.com/images /'.$ filename)) ' – rebeliagamer

+0

Это не работает. – Scolytus

+3

Это сообщит, что файл существует, как только клиент начинает его загружать, он не будет ждать завершения загрузки. – Barmar

-5

Согласовано с Хасаном. Вы можете проверить его, используя функцию php file_exist.

Сохраните ваше имя файла, которое вы и получаете, когда пользователь загружает файл (или переименованный файл, если вы его переименовываете) в любую таблицу в базе данных. Теперь ваш cron получит это имя из таблицы базы данных каждый раз, когда он будет запущен, и проверит, был ли этот файл загружен или нет.

<?php 
$filename = '/var/www/YOUR_UPLOAD_FOLDER/xyz.txt'; //get xyz name from database 

if (file_exists($filename)) { 
    // YOU CAN WORK WITH YOUR FILE AND CAN DELETE RELATIVE RECORD FROM DB TABLE. 
} else { 
    // YOU SHOULD WAIT WHILE FILE IS UPLOADING. 
} 
?> 
+0

Это просто не работает. – Scolytus

0

Проверяя сообщение об ошибке загрузки Вы можете подтвердить whethere файла полных загруженный или частичные загруженное

Если код ошибки загружаемом 3, то файл загружен частично

скажет загружаемого файл имя поля MYFILE

$error=$_FILES['myfile']['error']; 
if($error>0){ 
//Upload Error IS Present check what type of error 
switch($error){ 
    case 1: 
     // UPLOAD_ERR_INI_SIZE 
     // Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini. 
     break; 
    case 2: 
     // UPLOAD_ERR_FORM_SIZE 
     // Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form. 
     break; 
    case 3: 
     // UPLOAD_ERR_PARTIAL 
     // Value: 3; The uploaded file was only partially uploaded. 
     break; 
    case 4: 
     // UPLOAD_ERR_NO_FILE 
     // Value: 4; No file was uploaded. 
     break; 
    case 6: 
     // UPLOAD_ERR_NO_TMP_DIR 
     // Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3. 
     break; 
    case 7: 
     // UPLOAD_ERR_CANT_WRITE 
     // Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0. 
     break; 
    case 8: 
     // UPLOAD_ERR_EXTENSION 
     // Value: 8; A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help. Introduced in PHP 5.2.0. 
     break; 
} 

}else{ 
    //File IS Uploaded you can move or validate other things 
} 

В случае 3 вы можете проверить частично u pload

Если вы хотите отслеживать файл Загрузка через FTP программу, если вы работаете VSFTPD, то вы можете отслеживать

file=/var/log/vsftpd.log 
initial_files=`grep -c 'OK UPLOAD' $file`; 
while [ TRUE ] 
do 
current_files=`grep -c 'OK UPLOAD' $file`; 
if [ $current_files == $initial_files ]; then 
    echo "old File Not Uploaded"; 
else 
    echo "new File Uploaded Process New File"; 
new_file=`grep 'OK UPLOAD' $file | tail -1`; 
echo $new_file; 
initial_files=$current_files; 
fi 
sleep 1 
done 

любой проблемы в понимании пожалуйста ответ

+1

Он не использует сценарий загрузки на веб-странице, он загружается на FTP-сервер. Фоновый процесс должен проверить, завершена ли загрузка. – Barmar

2

держать SQL запись даты изменений и проверок если у вас есть модифицированный файл.

<?php 
$filename = 'somefile.txt'; 
if (file_exists($filename)) { 
echo "$filename was last modified: " . date ("F d Y H:i:s.", filemtime($filename)); 
} 
?> 
+0

Это сообщит, когда загрузка началась, она не сообщит, когда загрузка завершена. – Barmar

3

вы можете установить нить, чтобы получить подробную информацию с помощью: ll -h

и получить столбец размера и сравнивая его через определенный промежуток времени, если он остается неизменным в течение 2 или 3 интервала времени, то загрузки может быть закончено.

, если вам нужно более точное решение, и если вы ищете более сложного способа (но эффективный), чтобы сделать это, проверить это:

http://www.php.net/manual/en/function.inotify-read.php

Вы можете взять смотреть на эту example в ссылке, которую я дал, Вам нужно будет проверить код события IN_CLOSE_WRITE

Взято из: LINUX: how to detect that ftp file upload is finished

Смежные вопросы