У меня есть php-скрипт на веб-сервере, который загружает файл на другой удаленный сервер через ftp_put.
Как я могу показать текущую загрузку пользователя?
Единственная подобная система, которую я видел, – это загрузка файлов от пользователя, с помощью ajax-запросов для проверки локального размера загруженного файла на сервере.
Эквивалентной системой будут аякс-запросы к веб-серверу, которые затем проверяли размеры файлов на удаленном сервере и возвращали эти данные в клиентский файл пользователя.
Мне это кажется ужасно неэффективным. Есть ли способ лучше?
Если ftp-сервер на другом компьютере поддерживает команду REST
(перезагрузка загрузки с определенной точки), существует грязный способ реализовать это:
Образец кода:
$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
и извлечь прогресс.
Поэтому я предлагаю (и это всего лишь предложение, есть множество способов сделать это …)
exec()
для вызова curl
чтобы загрузить файл, создавая curl
в качестве фонового задания и перенаправляя вывод в некоторый файл, например, "curlprogress-$uploadId.txt"
upload_progress.php?id=$uploadId
upload_progress.php
проверяет "curlprogress-$uploadId.txt"
, извлекает и возвращает процент. 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);