PHP环境下FTP大文件下载提速咨询:1GB文件需从1小时降至20分钟内
优化PHP大文件FTP下载速度的方案
针对你用原生PHP FTP函数下载1GB大文件耗时超1小时的问题,结合高配置服务器和带宽的前提,以下是几个能将下载时间压缩到15-20分钟内的优化方案:
1. 启用FTP被动模式并调整缓冲区大小
原生ftp_connect默认使用主动模式,容易被防火墙或路由规则限制,导致传输速率低下。同时默认缓冲区过小也会拖慢传输效率。
修改后的代码:
<?php // FTP server details $ftp_server = "ftp.example.com"; $ftp_username = "username"; $ftp_userpass = "password"; $remote_file = "/path/to/remote/file.txt"; $local_file = "/path/to/local/file.txt"; // Establish an FTP connection $conn_id = ftp_connect($ftp_server) or die("Could not connect to $ftp_server"); // 调整传输缓冲区为1MB(默认通常为8KB) ftp_set_option($conn_id, FTP_BUFFERSIZE, 1024 * 1024); // Login to FTP server if (@ftp_login($conn_id, $ftp_username, $ftp_userpass)) { echo "Connected to $ftp_server as $ftp_username\n"; // 启用被动模式,避免防火墙拦截数据连接 ftp_pasv($conn_id, true); // Download the remote file and save it to the local file if (ftp_get($conn_id, $local_file, $remote_file, FTP_BINARY)) { echo "Successfully downloaded $remote_file to $local_file\n"; } else { echo "There was a problem while downloading $remote_file to $local_file\n"; } } else { echo "Could not login to $ftp_server\n"; } // Close the FTP connection ftp_close($conn_id); ?>
说明:被动模式让客户端主动发起数据连接,规避主动模式下的防火墙限制;增大缓冲区减少磁盘IO次数,提升传输效率。
2. 用cURL替代原生FTP函数
cURL的FTP实现优化更完善,支持更多底层参数调整,传输效率普遍高于原生PHP FTP函数。
示例代码:
<?php $ftp_server = "ftp.example.com"; $ftp_username = "username"; $ftp_userpass = "password"; $remote_file = "/path/to/remote/file.txt"; $local_file = "/path/to/local/file.txt"; $remote_url = "ftp://$ftp_username:$ftp_userpass@$ftp_server$remote_file"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $remote_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 启用被动模式 curl_setopt($ch, CURLOPT_FTP_USE_EPSV, true); // 设置1MB缓冲区 curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024 * 1024); // 直接写入本地文件,避免内存占用 $fp = fopen($local_file, 'wb'); curl_setopt($ch, CURLOPT_FILE, $fp); // 执行下载 $success = curl_exec($ch); if (!$success) { echo "Download failed: " . curl_error($ch) . "\n"; } else { echo "Successfully downloaded $remote_file to $local_file\n"; } // 清理资源 fclose($fp); curl_close($ch); ?>
说明:cURL直接将数据写入文件,避免内存溢出,同时底层优化的传输逻辑能有效提升速率。
3. 多线程分片下载(最大化带宽利用)
单连接FTP传输受限于协议本身的单流速率,分片多线程下载可以同时建立多个连接,充分利用带宽资源。
以下是基于curl_multi的多线程分片下载示例:
<?php $ftp_server = "ftp.example.com"; $ftp_username = "username"; $ftp_userpass = "password"; $remote_file = "/path/to/remote/file.txt"; $local_file = "/path/to/local/file.txt"; $chunk_size = 1024 * 1024 * 100; // 每个分片100MB // 获取远程文件大小 $conn_id = ftp_connect($ftp_server); ftp_login($conn_id, $ftp_username, $ftp_userpass); ftp_pasv($conn_id, true); $file_size = ftp_size($conn_id, $remote_file); ftp_close($conn_id); if ($file_size == -1) { die("Failed to get remote file size\n"); } $total_chunks = ceil($file_size / $chunk_size); $chunks = []; $mh = curl_multi_init(); // 创建每个分片的下载请求 for ($i = 0; $i < $total_chunks; $i++) { $start = $i * $chunk_size; $end = min(($i + 1) * $chunk_size - 1, $file_size - 1); $chunk_file = "$local_file.part$i"; $ch = curl_init(); $url = "ftp://$ftp_username:$ftp_userpass@$ftp_server$remote_file"; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RANGE, "$start-$end"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_FTP_USE_EPSV, true); $fp = fopen($chunk_file, 'wb'); curl_setopt($ch, CURLOPT_FILE, $fp); curl_multi_add_handle($mh, $ch); $chunks[] = ['ch' => $ch, 'fp' => $fp, 'file' => $chunk_file]; } // 执行多连接下载 $running = null; do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); // 合并分片文件 $final_fp = fopen($local_file, 'wb'); foreach ($chunks as $chunk) { fseek($chunk['fp'], 0); stream_copy_to_stream($chunk['fp'], $final_fp); fclose($chunk['fp']); curl_multi_remove_handle($mh, $chunk['ch']); unlink($chunk['file']); } fclose($final_fp); curl_multi_close($mh); echo "Successfully downloaded and merged $remote_file to $local_file\n"; ?>
说明:将大文件拆分为多个分片并行下载,完成后合并为完整文件。注意需确保FTP服务器支持RANGE请求(大部分主流FTP服务器都支持)。
内容的提问来源于stack exchange,提问作者Raja N
相关产品推荐
相关产品推荐

