PHP ftp_nb_continue() 函数用于继续执行非阻塞的FTP操作,通常与 ftp_nb_get() 或 ftp_nb_put() 等非阻塞函数配合使用。
ftp_nb_continue(resource $ftp): int
| 参数 | 描述 |
|---|---|
ftp |
必需。FTP连接的标识符,由ftp_connect()或ftp_ssl_connect()返回 |
FTP_FAILED (0) - 传输失败FTP_FINISHED (1) - 传输完成FTP_MOREDATA (2) - 传输仍在继续ftp_nb_continue() 主要用于以下非阻塞FTP函数:
ftp_nb_get() - 从FTP服务器下载文件(非阻塞)ftp_nb_put() - 上传文件到FTP服务器(非阻塞)ftp_nb_fget() - 从FTP服务器下载文件到已打开的文件(非阻塞)ftp_nb_fput() - 将已打开的文件上传到FTP服务器(非阻塞)<?php
// 连接FTP服务器
$ftp_server = "ftp.example.com";
$ftp_user = "username";
$ftp_pass = "password";
$ftp_conn = ftp_connect($ftp_server) or die("无法连接到 $ftp_server");
// 登录
if (!ftp_login($ftp_conn, $ftp_user, $ftp_pass)) {
die("登录失败");
}
// 启用被动模式(某些服务器需要)
ftp_pasv($ftp_conn, true);
// 开始非阻塞下载
$remote_file = "largefile.zip";
$local_file = "download.zip";
// 开始非阻塞下载,返回FTP_FAILED或FTP_MOREDATA
$result = ftp_nb_get($ftp_conn, $local_file, $remote_file, FTP_BINARY);
// 循环检查传输状态
while ($result == FTP_MOREDATA) {
echo "正在下载... ";
// 可以在这里执行其他任务
// 例如:更新进度条、检查用户输入等
// 继续传输
$result = ftp_nb_continue($ftp_conn);
// 添加短暂延迟,避免过度占用CPU
usleep(100000); // 0.1秒
}
// 检查最终结果
if ($result == FTP_FINISHED) {
echo "下载完成!文件已保存为: $local_file";
} elseif ($result == FTP_FAILED) {
echo "下载失败!";
}
// 关闭连接
ftp_close($ftp_conn);
?>
<?php
// 简单的进度模拟函数
function showProgress($message) {
static $counter = 0;
$counter++;
$progressChars = ['|', '/', '-', '\\'];
$char = $progressChars[$counter % 4];
echo "\r" . $message . " " . $char;
flush(); // 立即输出
}
// 建立FTP连接
$ftp_conn = ftp_connect('localhost');
if ($ftp_conn === false) {
die("无法连接FTP服务器");
}
if (!ftp_login($ftp_conn, 'user', 'pass')) {
die("登录失败");
}
ftp_pasv($ftp_conn, true); // 启用被动模式
// 开始非阻塞上传
$local_file = "upload.txt";
$remote_file = "uploads/upload.txt";
// 检查本地文件是否存在
if (!file_exists($local_file)) {
die("本地文件不存在: $local_file");
}
$result = ftp_nb_put($ftp_conn, $remote_file, $local_file, FTP_ASCII, FTP_NONBLOCK);
$start_time = time();
$max_timeout = 60; // 最大超时时间(秒)
while ($result == FTP_MOREDATA) {
// 显示进度
showProgress("正在上传文件...");
// 检查是否超时
if ((time() - $start_time) > $max_timeout) {
echo "\n上传超时!";
break;
}
// 继续传输
$result = ftp_nb_continue($ftp_conn);
// 短暂延迟
usleep(50000); // 0.05秒
}
echo "\n"; // 换行
if ($result == FTP_FINISHED) {
echo "上传成功!远程文件: $remote_file";
} elseif ($result == FTP_FAILED) {
echo "上传失败!";
}
ftp_close($ftp_conn);
?>
<?php
class NonBlockingFTP {
private $ftp_conn;
private $active_transfers = [];
public function connect($server, $username, $password) {
$this->ftp_conn = ftp_connect($server);
if (!$this->ftp_conn) {
return false;
}
return ftp_login($this->ftp_conn, $username, $password);
}
public function downloadFiles($file_list) {
$results = [];
foreach ($file_list as $remote_file => $local_file) {
// 开始非阻塞下载
$result = ftp_nb_get($this->ftp_conn, $local_file, $remote_file, FTP_BINARY);
if ($result == FTP_FAILED) {
$results[$remote_file] = "开始下载失败";
} else {
$this->active_transfers[] = [
'remote' => $remote_file,
'local' => $local_file,
'status' => $result
];
$results[$remote_file] = "下载已开始";
}
}
return $results;
}
public function processTransfers() {
$completed = [];
$still_active = [];
foreach ($this->active_transfers as $transfer) {
if ($transfer['status'] == FTP_MOREDATA) {
$result = ftp_nb_continue($this->ftp_conn);
if ($result == FTP_FINISHED) {
$completed[] = $transfer['remote'];
} elseif ($result == FTP_MOREDATA) {
$transfer['status'] = $result;
$still_active[] = $transfer;
} else {
$still_active[] = $transfer; // 保持活动状态
}
} else {
$still_active[] = $transfer;
}
}
$this->active_transfers = $still_active;
return $completed;
}
public function hasActiveTransfers() {
return !empty($this->active_transfers);
}
public function close() {
if ($this->ftp_conn) {
ftp_close($this->ftp_conn);
}
}
}
// 使用示例
$ftp = new NonBlockingFTP();
if ($ftp->connect('localhost', 'user', 'pass')) {
// 要下载的文件列表
$files_to_download = [
'server/file1.txt' => 'local/file1.txt',
'server/file2.txt' => 'local/file2.txt',
'server/file3.txt' => 'local/file3.txt'
];
echo "开始批量下载...\n";
$ftp->downloadFiles($files_to_download);
// 处理传输
$count = 0;
$max_iterations = 100; // 防止无限循环
while ($ftp->hasActiveTransfers() && $count < $max_iterations) {
$completed = $ftp->processTransfers();
if (!empty($completed)) {
foreach ($completed as $file) {
echo "完成: $file\n";
}
}
// 模拟其他工作
echo ".";
$count++;
usleep(200000); // 0.2秒延迟
}
echo "\n处理完成\n";
$ftp->close();
} else {
echo "连接失败\n";
}
?>
ftp_nb_continue()直到传输完成usleep())以避免过度占用CPU| 阻塞函数 | 非阻塞函数 | 特点 |
|---|---|---|
ftp_get() |
ftp_nb_get() |
非阻塞版本需要配合ftp_nb_continue()使用 |
ftp_put() |
ftp_nb_put() |
传输过程中可以执行其他操作 |
| 脚本会阻塞直到传输完成 | 脚本可以继续执行其他任务 | 适合大文件传输或需要用户交互的场景 |
ftp_nb_get() - 非阻塞方式从FTP服务器下载文件ftp_nb_put() - 非阻塞方式上传文件到FTP服务器ftp_nb_fget() - 非阻塞方式下载文件到已打开的文件ftp_nb_fput() - 非阻塞方式上传已打开的文件ftp_get() - 阻塞方式下载文件ftp_put() - 阻塞方式上传文件