PHP Conference Japan 2024

ftp_get

(PHP 4, PHP 5, PHP 7, PHP 8)

ftp_get从 FTP 服务器下载文件

描述

ftp_get(
    FTP\Connection $ftp,
    字符串 $local_filename,
    字符串 $remote_filename,
    整数 $mode = FTP_BINARY,
    整数 $offset = 0
): 布尔值

ftp_get() 从 FTP 服务器检索远程文件,并将其保存到本地文件。

参数

ftp

一个 FTP\Connection 实例。

local_filename

本地文件路径(如果文件已存在,则会被覆盖)。

remote_filename

远程文件路径。

mode

传输模式。必须是 FTP_ASCIIFTP_BINARY

offset

开始下载的远程文件中的位置。

返回值

成功时返回 true,失败时返回 false

变更日志

版本 描述
8.1.0 ftp 参数现在期望一个 FTP\Connection 实例;以前,期望一个 资源
7.3.0 mode 参数现在是可选的。以前它是强制性的。

示例

示例 #1 ftp_get() 示例

<?php

// 定义一些变量
$local_file = 'local.zip';
$server_file = 'server.zip';

// 设置基本连接
$ftp = ftp_connect($ftp_server);

// 使用用户名和密码登录
$login_result = ftp_login($ftp, $ftp_user_name, $ftp_user_pass);

// 尝试下载 $server_file 并保存到 $local_file
if (ftp_get($ftp, $local_file, $server_file, FTP_BINARY)) {
echo
"已成功写入 $local_file\n";
} else {
echo
"出现问题\n";
}

// 关闭连接
ftp_close($ftp);

?>

参见

  • ftp_pasv() - 打开或关闭被动模式
  • ftp_fget() - 从 FTP 服务器下载文件并保存到打开的文件中
  • ftp_nb_get() - 从 FTP 服务器检索文件并将其写入本地文件(非阻塞)
  • ftp_nb_fget() - 从 FTP 服务器检索文件并将其写入打开的文件(非阻塞)

添加注释

用户贡献的笔记 14 条笔记

36
CuDi
15 年前
我今天尝试从我的 Web 服务器上通过 ftp 传输一个 7mb 的文件。

我直接复制了这个示例,它告诉我。

端口命令成功
"出现问题"

我以为是文件大小的原因。
但我猜可能是我的防火墙造成的。

所以我使 ftp 连接处于被动状态

<?PHP

...
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
ftp_pasv($conn_id, true);

?>

再次运行脚本 & 它工作正常。

希望这对某些人有所帮助
36
bob at notallhere dot com
11 年前
不想使用中间文件?使用“php://output”作为文件名,然后使用输出缓冲捕获输出。

ob_start();
$result = ftp_get($ftp, "php://output", $file, FTP_BINARY);
$data = ob_get_contents();
ob_end_clean();

不要忘记检查 $result 以确保没有错误。之后,根据需要操作 $data 变量。
14
ramiro at qusarcr dot com
22 年前
请记住,如果本地机器上有相同名称的文件,ftp_get 会覆盖该文件。
10
anomie at users dot sf dot net
17 年前
为什么没有“ftp_get_contents”函数,我不知道。模拟一个需要一些工作,但这是可行的。
<?php
function ftp_get_contents($ftp_stream, $remote_file, $mode, $resume_pos=null){
$pipes=stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
if(
$pipes===false) return false;
if(!
stream_set_blocking($pipes[1], 0)){
fclose($pipes[0]); fclose($pipes[1]);
return
false;
}
$fail=false;
$data='';
if(
is_null($resume_pos)){
$ret=ftp_nb_fget($ftp_stream, $pipes[0], $remote_file, $mode);
} else {
$ret=ftp_nb_fget($ftp_stream, $pipes[0], $remote_file, $mode, $resume_pos);
}
while(
$ret==FTP_MOREDATA){
while(!
$fail && !feof($pipes[1])){
$r=fread($pipes[1], 8192);
if(
$r==='') break;
if(
$r===false){ $fail=true; break; }
$data.=$r;
}
$ret=ftp_nb_continue($ftp_stream);
}
while(!
$fail && !feof($pipes[1])){
$r=fread($pipes[1], 8192);
if(
$r==='') break;
if(
$r===false){ $fail=true; break; }
$data.=$r;
}
fclose($pipes[0]); fclose($pipes[1]);
if(
$fail || $ret!=FTP_FINISHED) return false;
return
$data;
}
?>

类似的方法也可以用来编写 ftp_put_contents 函数。
4
来自 ruggfamily.com 的 Nate
16 年前
这是一个快速函数,它根据文件的扩展名确定要使用的正确模式。

<?php
function get_ftp_mode($file)
{
$path_parts = pathinfo($file);

if (!isset(
$path_parts['extension'])) return FTP_BINARY;
switch (
strtolower($path_parts['extension'])) {
case
'am':case 'asp':case 'bat':case 'c':case 'cfm':case 'cgi':case 'conf':
case
'cpp':case 'css':case 'dhtml':case 'diz':case 'h':case 'hpp':case 'htm':
case
'html':case 'in':case 'inc':case 'js':case 'm4':case 'mak':case 'nfs':
case
'nsi':case 'pas':case 'patch':case 'php':case 'php3':case 'php4':case 'php5':
case
'phtml':case 'pl':case 'po':case 'py':case 'qmail':case 'sh':case 'shtml':
case
'sql':case 'tcl':case 'tpl':case 'txt':case 'vbs':case 'xml':case 'xrc':
return
FTP_ASCII;
}
return
FTP_BINARY;
}

// 示例用法
ftp_get($conn_id, $local_file, $server_file, get_ftp_mode($server_file));
?>
7
[email protected]
15 年前
ftp_sync 是一种遍历服务器上目录结构并将每个目录和文件复制到本地相同位置的方法。



<?php
$ftp_server
= "ftp.example.com";
$conn_id = ftp_connect ($ftp_server)
or die(
"无法连接到 $ftp_server");

$login_result = ftp_login($conn_id, "user", "pass");
if ((!
$conn_id) || (!$login_result))
die(
"FTP连接失败");

ftp_sync ("DirectoryToCopy"); // 如果您在当前目录中,请使用 "."

ftp_close($conn_id);

// ftp_sync - 复制目录和文件结构
function ftp_sync ($dir) {

global
$conn_id;

if (
$dir != ".") {
if (
ftp_chdir($conn_id, $dir) == false) {
echo (
"更改目录失败: $dir<BR>\r\n");
return;
}
if (!(
is_dir($dir)))
mkdir($dir);
chdir ($dir);
}

$contents = ftp_nlist($conn_id, ".");
foreach (
$contents as $file) {

if (
$file == '.' || $file == '..')
continue;

if (@
ftp_chdir($conn_id, $file)) {
ftp_chdir ($conn_id, "..");
ftp_sync ($file);
}
else
ftp_get($conn_id, $file, $file, FTP_BINARY);
}

ftp_chdir ($conn_id, "..");
chdir ("..");

}
?>
1
Aditya P dot Bhatt (adityabhai at gmail dot com)
16 年前
<?php
// 定义一些变量
$folder_path = "您的文件夹路径";
$local_file = "本地文件路径";
$server_file = "服务器文件路径";

//-- 连接设置
$ftp_server = "IP地址"; // FTP服务器地址。
$ftp_user_name = "用户名"; // 用户名
$ftp_user_pass = "密码"; // 密码
#$destination_file = "文件路径";

// 设置基本连接
$conn_id = ftp_connect($ftp_server);

// 使用用户名和密码登录
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// 尝试下载 $server_file 并保存到 $local_file
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
echo
"已成功写入 $local_file\n";
} else {
echo
"出现问题\n";
}

// 关闭连接
ftp_close($conn_id);
?>
0
mpatnode at yahoo dot com
6年前
请注意,PHP 仍然默认使用 FTP 活动模式,该模式现在几乎不再使用,因为防火墙的出现。不要忘记在您的 ftp_login 后添加 ftp_pasv($conn, true)。
0
anomie at users dot sf dot net
17 年前
糟糕。_nb_ 仅指从 FTP 服务器读取,并且套接字对中的缓冲区仅约 364 字节。因此,它不适用于大于此大小的文件。
0
thivierr at telus dot net
21年前
如果您之前下载过文件(例如巨大的 Web 日志),并且只想获取剩余部分,请执行以下操作

$local_file_size = filesize($local_file_path);
$get_result = ftp_get($conn_id, $local_file_path, $remote_file_path, FTP_BINARY, $local_file_size);

无论本地文件是否已存在,此代码都适用。您应该首先测试以确保本地文件的大小不超过远程文件的大小。
-1
administrator at gesoft dot org
18年前
大家好,

如果有人尝试将文件下载到同一个本地文件(某些临时文件),如这里所示

<?php
foreach ($files as $key=>$path) {
...
$result = ftp_get($ftpConnId, 'temp.tmp', $path, FTP_BINARY);
...
}
?>

请考虑您在下载(获取)整个文件时会遇到很大的问题。换句话说,'temp.tmp' 文件的大小始终与第一个下载的文件的大小相同,而不管正在下载的文件的实际大小如何。我不知道原因是什么!

如果有人认为问题仅仅在于获取正确的文件大小(您可以使用 filssize() 函数获取),那他就错了。下载文件的大小在本质上不等于源文件的大小,这意味着 fflush() 函数无法解决问题(我也尝试过)。

最终找到了解决方案:在下载文件之前,您需要删除本地文件(如果存在'temp.tmp')。因此,有效的代码将如下所示

<?php
foreach ($files as $key=>$path) {
...
if (
file_exists('temp.tmp')) {
unlink('temp.tmp');
}
$result = ftp_get($ftpConnId, 'temp.tmp', $path, FTP_BINARY);
...
}
?>

祝您脚本编写顺利!

Vitali Simsive
-1
miki at epoch dot co dot il
11 年前
如果您运行了示例并发现它在 90 秒后失败(超时)。

然后尝试添加
<?php
ftp_pasv
($ftp_conn, true);
?>
-2
corey-holzer at nyc dot rr dot com
20年前
零大小文件不是副作用。当 ftp_get 启动时,它首先要做的是创建它将向其中流式传输数据的 inode/文件,这是一个零大小的文件,其名称是您为本地文件指定的名称。下载失败时,它会保留文件。
-3
scott dot chu at udngroup dot com
8年前
我建议使用 ftp_fget() 而不是 ftp_get(),因为后者只返回 TRUE 或 FALSE,并且没有明显的方法来获取失败的原因。

使用 ftp_fget,您必须将文件句柄作为本地文件传递,因此您必须首先执行 fopen()。通过这种方式,您可以在调用 fopen() 时找到“权限被拒绝”问题。如果您使用 ftp_get(),则无法找到此错误原因。

在我的例子中,我使用'nobody'运行 httpd,并使用'haha'创建 FTP 本地文件夹。由于我当时使用了 ftp_get(),因此花了很长时间才找到那个“权限被拒绝”问题。
To Top