Получение прогресса ftp_put

У меня есть php-скрипт на веб-сервере, который загружает файл на другой удаленный сервер через ftp_put.

Как я могу показать текущую загрузку пользователя?

Единственная подобная система, которую я видел, – это загрузка файлов от пользователя, с помощью ajax-запросов для проверки локального размера загруженного файла на сервере.

Эквивалентной системой будут аякс-запросы к веб-серверу, которые затем проверяли размеры файлов на удаленном сервере и возвращали эти данные в клиентский файл пользователя.

Мне это кажется ужасно неэффективным. Есть ли способ лучше?

Related of "Получение прогресса ftp_put"

Если ftp-сервер на другом компьютере поддерживает команду REST (перезагрузка загрузки с определенной точки), существует грязный способ реализовать это:

  1. создать временный файл
  2. поместите X байтов в этот файл из файла, который вы хотите загрузить
  3. загрузить файл temp
  4. записывать статус в другой файл (или сеанс, но не уверен, что он будет работать)
  5. добавить еще один файл X в файл temp
  6. Загрузить стартовый формат файла temp X байт
  7. crite status to file
  8. повторите 5-7, пока не будет загружен весь файл
  9. удалять временные и статусные файлы.

Образец кода:

 $fs = filesize('file.bin'); define('FTP_CHUNK_SIZE', intval($fs * 0.1) ); // upload ~10% per iteration $ftp = ftp_connect('localhost') or die('Unable to connect to FTP server'); ftp_login($ftp, 'login', 'pass') or die('FTP login failed'); $localfile = fopen('file.bin','rb'); $i = 0; while( $i < $fs ) { $tmpfile = fopen('tmp_ftp_upload.bin','ab'); fwrite($tmpfile, fread($localfile, FTP_CHUNK_SIZE)); fclose($tmpfile); ftp_put($ftp, 'remote_file.bin', 'tmp_ftp_upload.bin', FTP_BINARY, $i); // Remember to put $i as last argument above $progress = (100 * round( ($i += FTP_CHUNK_SIZE) / $fs, 2 )); file_put_contents('ftp_progress.txt', "Progress: {$progress}%"); } fclose($localfile); unlink('ftp_progress.txt'); unlink('tmp_ftp_upload.bin'); // delete when done 

И файл для проверки с помощью ajax:

 if(file_exists('ftp_progress.txt')) echo file_get_contents('ftp_progress.txt'); else echo 'Progress: 0%'; exit; 

Функция PHP ftp_put не вернется, пока она не завершится, так как вы сказали, единственный способ (используя ftp_put ) – опросить удаленный FTP-сервер и посмотреть, какой размер файла, который может не работать, потому что часто загрузка идет к временному файлу, только вводятся в действие, когда они заполняются на 100%.

Что бы я хотел сделать, это создать второй процесс для загрузки и использовать что-то вроде wget или curl . Вы можете проанализировать вывод из curl и извлечь прогресс.

Поэтому я предлагаю (и это всего лишь предложение, есть множество способов сделать это …)

  1. Пользователь загружает файл в ваш скрипт PHP
  2. Ваш PHP-скрипт генерирует уникальный идентификатор ID $ uploadId
  3. Ваш PHP-скрипт использует exec() для вызова curl чтобы загрузить файл, создавая curl в качестве фонового задания и перенаправляя вывод в некоторый файл, например, "curlprogress-$uploadId.txt"
  4. Ваш PHP-скрипт отображает страницу для пользователя, который периодически выполняет вызов AJAX на что-то вроде: upload_progress.php?id=$uploadId
  5. upload_progress.php проверяет "curlprogress-$uploadId.txt" , извлекает и возвращает процент.
  6. Найдите способ очистки файлов состояния curl . Возможно, вместо того, чтобы выполнять curl непосредственно на шаге 3, вы выполняете скрипт bash, который вызывает curl и автоматически перенаправляет его вывод, удаляя файл, когда это будет сделано. Или просто upload_progress.php удалите "curlprogress-$uploadId.txt" если прогресс составляет 100%.

Обратите внимание, что это непросто . Я бы предоставил код, но мы говорим о часах разработки здесь 😉

Он может быть легко реализован с использованием протоколов протокола FTP URL :

 $url = "ftp://username:password@ftp.example.com/remote/dest/path/file.zip"; $local_path = "/local/source/path/file.zip"; $size = filesize($local_path) or die("Cannot retrieve size file"); $hout = fopen($url, "wb") or die("Cannot open destination file"); $hin = fopen($local_path, "rb") or die("Cannot open source file"); while (!feof($hin)) { $buf = fread($hin, 10240); fwrite($hout, $buf); echo "\r".intval(ftell($hin)/$size*100)."%"; } echo "\n"; fclose($hin); fclose($hout);