【PHP库】phpseclib

需求场景说明

对接的三方商家需要进行文件传输,并且对方提供的方式是 sftp 的服务器账号,我们需根据他们提供的目录进行下载和上传指定文件。

安装

composer require phpseclib/phpseclib:~3.0 

使用sftp功能

1.新建并设置config/sftp.php文件

 return [     'sftp' => [         'host'   => env('SFTP_HOST', '127.0.0.1'),         'port'   => env('SFTP_PORT', 22),         'user' => env('SFTP_USE', null),         'password' => env('SFTP_PASSWORD', null),     ], ]; 

2.配置.env文件

SFTP_HOST=127.0.0.1 SFTP_PORT=22 SFTP_USE=user SFTP_PASSWORD=password 

3.封装 app/Utils/SftpHelper.php调用库文件,通过单例可设置不同的 sftp 服务器

namespace App/Utils;  use phpseclib3/Net/SFTP;  class SftpHelper {     private static $instance = [];      public static function getInstance($key='sftp')     {         if (!isset(self::$instance[$key])) {             $config = ConfigHelper::getInstance()->read('sftp.'.$key);             self::$instance[$key] = new SFTP($config['host'], $config['port']);             self::$instance[$key]->login($config['user'], $config['password']);         }          return self::$instance[$key];     } } 

4.使用方法说明

  • nlist:获取指定目录下的文件列表,包括子目录,(默认不会递归子目录下的文件)
  • is_readable: 判断文件是否有读权限
  • chmod:修改文件/目录权限,默认不递归
  • get:获取文件,默认获取文件内容。
  • is_dir:是否存在该目录
  • mkdir:创建目录
  • rename: 将文件重命名
  • put:上传文件

5.访问 sftp 服务器并下载文件到本地

5.1 读取指定服务器下的文件,并循环处理每个文件

5.2 下载远程文件到当前服务器的指定位置,并创建待处理文件记录表

说明:创建文件处理表可使文件读取逻辑失败时,可重复处理,并且不需要多次访问 sftp 服务器,进行逻辑解耦

5.3 创建文件记录数据后将服务器上的文件移到归档目录,避免重复读取

// 连接sftp服务器并登录 $sftp = SftpHelper::getInstance('sftp'); // 获取目录下的文件列表(不递归) $file_list = $sftp->nlist($remote_dir);  // 循环文件列表,获取处理数据 foreach ($file_list as $file_name) {     // 跳过不处理的目录     if (in_array($file_name, ['.', '..', 'Archive'])) {         continue;     }      // 拼接完整的服务器文件路径     $remote_file = $remote_dir.$file_name;      // 设置本地存储的目录     $save_path = env('FILE_PATH', '/data/storage/sftp/')."{$file_type}/";     File::exists($save_path) or (File::makeDirectory($save_path, 0777, true) && @chmod($save_path, 0777));      // 完整的本地路径     $local_file = $save_path. $file_name;     // 拉取sftp文件到本地目录     if (!file_exists($local_file)) {         if (!$sftp->is_readable($remote_file)) {             $sftp->chmod('0777', $remote_file);         }          $sftp->get($remote_file, $local_file);     }      // 添加文件日志(同一个远程文件不重复拉取)     // 后续可单独增加文件读取逻辑,使文件内容处理失败时可重复处理,并且不需要重复访问 sftp 服务器去读取远程文件     SftpFile::updateOrCreate([         'remote_dir'  => $remote_file,     ], [         'action'     => $file_type, // 文件类型         'filename'   => $file_name, // 文件名         'filepath'   => $local_file, // 本地服务器路径     ]);          // 日志创建成功之后再将文件移到Archive目录下,避免重复读取     if (!$sftp->is_dir($remote_dir.'Archive/')) {         // 没有则创建Archive目录         $sftp->mkdir($remote_dir.'Archive/');     }      // 已读取的文件移到子目录Archive     $sftp->rename($remote_file, "Archive/{$remote_file}"); } 

6.上传文件到 sftp 服务器的指定位置

// 读取待处理的文件列表 $file_list = SftpFile::where([     'action' => $file_type,     'state'  => 1 ])->get(); if (count($file_list) <= 0) {     return; }  // 连接sftp服务器并登录 $mk_sftp = SftpHelper::getInstance('sftp');  foreach ($file_list as $file) {      // 校验推送的文件是否存在     if (!file_exists($file->filepath)) {         throw new ParamsException('推送的文件不存在');     }      $file_path = $file->filepath;     $remote_file = $file->remote_dir;      // 推送文件到sftp服务器     // SFTP::SOURCE_LOCAL_FILE 表示以文件的形式,不设置时表示是按字符串形式上传     $put_res = $mk_sftp->put($remote_file, $file_path, SFTP::SOURCE_LOCAL_FILE);      if ($put_res) {         $file->state = 1;         $file->save();     } } 

7.读取文件内容

// 当前php.ini配置的是128M ini_set('memory_limit', '300M');  $local_file = $file_info['filepath']; $remote_file = $file_info['remote_dir'];  // 读取文件数据 $fp = fopen($local_file, 'r');  $file_data = []; while (!feof($fp)) {      $row_str = fgets($fp); // 逐行读取。如果fgets不写length参数,默认是读取1k。     $item = explode(',', trim($row_str));          // 跳过表头         // 将行数据转成指定的键值对 }  return $file_data;  

参考教程

商匡云商
Logo
对比商品
  • 合计 (0)
对比
0
购物车