需求场景说明

对接的三方商家需要进行文件传输,并且对方提供的方式是 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;

参考教程

【PHP库】phpseclib - sftp远程文件操作的更多相关文章

  1. SFTP远程文件上传

    远程服务器remote_host=192.168.29.142用户为remote_www,用户当前目录为/home/remote_www 本地服务器local_host=192.168.29.135用 ...

  2. 配置openssh实现sftp远程文件上传

    客服端:winscp等ftp/sftp客户端 服务器:阿里云默认使用的openssh 需求:可以sftp远程传输文件到服务器固定文件夹下,不可远程ssh登录 步骤: 1. 建立系统用户ftpuser及 ...

  3. scp & cat远程文件操作

    对拷文件夹 (包括文件夹本身) scp -r /home/wwwroot/www/charts/util root@192.168.1.65:/home/wwwroot/limesurvey_back ...

  4. java远程文件操作

    有时在项目中,会有专门的文件服务器(windows),这个时候我们需要对文件进行操作时,就不能像操作本地文件那样操作文件服务器的文件.这时候就可以用SmbFile来操作了. 首先添加jar包,mave ...

  5. delphi使用Chilkat 组件和库从SFTP下载文件

    官网地址:https://www.example-code.com/delphiDll/default.asp 实例代码:(不包括全局解锁)  密码生成器:https://www.cnblogs.co ...

  6. Python Requests库 form-data 上传文件操作

    请求数据示例: ------WebKitFormBoundaryKLoWgrA4O40MayHM Content-Disposition: form-data; name="id" ...

  7. 《Java核心技术卷二》笔记(二)文件操作和内存映射文件

    文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...

  8. Python的高级文件操作(shutil模块)

    Python的高级文件操作(shutil模块) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果让我们用python的文件处理来进行文件拷贝,想必很多小伙伴的思路是:使用打开2个 ...

  9. 文件系统之-JAVA Sftp远程操作:

    转载:http://blog.csdn.net/lee272616/article/details/52789018 java远程操作文件服务器(linux),使用sftp协议版本会持续更新,当前版本 ...

随机推荐

  1. 如何实现将拖动物体限制在某个圆形内--实现方式vue3.0

    如何实现蓝色小圆可拖动,并且边界限制在灰色大圆内?如下所示 需求源自 业务上遇到一个组件需求,设计师设计了一个"脸型整合器"根据可拖动小圆的位置与其它脸型的位置关系计算融合比例 如 ...

  2. 翻页组件page-flip调用问题

    翻页组件重新调用解决方案 翻页组件:page-flip import { PageFlip } from 'page-flip' pagefile() { //绘制翻页 this.pageFlip = ...

  3. git指令使用

    仓库为空,本地创建git项目之后提交到仓库中1.创建项目文件夹(本地git仓库)2.在项目文件夹中右键:选择Git Bash3.初始化项目:git init -- 会出现一个.git的隐藏文件夹4.将 ...

  4. 基于云服务MRS构建DolphinScheduler2调度系统

    摘要:本文介绍如何搭建DolphinScheduler并运行MRS作业. 本文分享自华为云社区<基于云服务MRS构建DolphinScheduler2调度系统>,作者: 啊喔YeYe . ...

  5. 简历应该怎么写,HR看一篇简历仅需要5秒吗,简历模板大全

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 最近有很多小伙伴问奇哥,说奇哥 ...

  6. dubbo是如何实现可扩展的?(二)

    牛逼的框架,看似复杂难懂,思路其实很清晰.---me 上篇文章,在整体扩展思路上进行了源码分析,比较粗糙,现在就某些点再详细梳理下. dubbo SPi的扩展,基于一类.三注解. 一类是Extensi ...

  7. kubernetes之常用核心资源对象

    部门产品线本身是做DEVOPS平台,最近部署架构也在往K8S上靠了,不得不学一下K8S.自己搭建了K8S集群与harbor仓库来学习. 1.kubernetes之常用核心资源对象 1.1.K8s服务部 ...

  8. ABAP CDS - DEFINE VIEW, name_list

    Syntax ... ( name1, name2, ... ) ... Effect Defines the element names of a CDS view in ABAP CDS in a ...

  9. 国外价值10K+美金的Python面试题,珍藏已久,含泪放了出来

    兄弟们,没吹牛皮,一哥们在国外面试的时候,就是要他做的这个,直接给他说,做出来了给你15K(单位是刀),做不出来就拜拜~ 大兄弟当时就不服了,这不是看不起我么,分分钟就给整完了~ 我上我也行系列: 唠 ...

  10. dotnet 控制台 使用 Microsoft.Maui.Graphics 配合 Skia 进行绘图入门

    本文将告诉大家如何在 dotnet 的控制台模式下,采用 MAUI 自绘库 Microsoft.Maui.Graphics 进行绘图,设置 Microsoft.Maui.Graphics 底层调用 M ...