需求场景说明

对接的三方商家需要进行文件传输,并且对方提供的方式是 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. 好客租房21-react组件的两种创建方式(函数组件)

    1使用函数创建组件 函数组件:使用js的函数或者箭头函数创建的组件 约定1:函数组件名称必须以 开头 约定2:函数组件必须有返回值 表示该组件的结构 如果返回值为null 表示不渲染任何内容 2.1使 ...

  2. Git 不识别文件名字母大小写变化

    问题 今天为一个项目撰写持续构建计划,撰写 Jenkinsfile 之后进行构建时报错: [2022-05-23 16:54:21] unable to prepare context: unable ...

  3. python将test01文件夹中的文件剪切到test02文件夹中

    将test01文件夹中的文件剪切到test02文件夹中 import shutil import os def remove_file(old_path, new_path): print(old_p ...

  4. 第06组 Alpha冲刺 (2/6)

    目录 1.1 基本情况 1.2 冲刺概况汇报 1.郝雷明 2. 方梓涵 3. 黄少丹 4. 董翔云 5.曾丽莉 6. 詹鑫冰 7.鲍凌函 8.杜筱 9.曹兰英 10. 吴沅静 1.3 冲刺成果展示 1 ...

  5. 数据库常用DDL语句

    一.创建表 CREATE TABLE TABLE_NAME( #create table 表名 ID INT(4) PRIMARY KEY, #字段名 数据类型 完整性约束条件 NAME VARCHA ...

  6. .NET C#基础(6):命名空间 - 组织代码的利器

    0. 文章目的   面向C#新学者,介绍命名空间(namespace)的概念以及C#中的命名空间的相关内容 1. 阅读基础   理解C与C#语言的基础语法 2. 名称冲突与命名空间 2.1 一个生活例 ...

  7. 关闭StackExchange等平台的privacy收集窗口

    技术背景 当我们打开一个StackExchange页面的时候,经常会出现一个很大的privacy收集窗口,而且不管怎么点都关闭不了,比如像下图这样: 如果屏幕足够大,影响可能也不是很大,但是关键是对于 ...

  8. JZOJ 5409 Fantasy & NOI 2010 超级钢琴 题解

    其实早在 2020-12-26 的比赛我们就做过 5409. Fantasy 这可是紫题啊 题目大意 给你一个序列,求长度在 \([L,R]\) 区间内的 \(k\) 个连续子序列的最大和 题解 如此 ...

  9. 一张图进阶 RocketMQ - NameServer

    前言 「三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦.」 一张图进阶 RocketMQ 图 ...

  10. 基于web3D展示技术的煤矿巷道3D可视化系统

    地下开采离不开巷道工程.煤矿的生产.运输.排水.通风等各个环节都少不了巷道的支持.在煤矿智能化建设被提上日程的今天,巷道工程的智能化.可视化建设也成了行业趋势.尤其是复杂的井下作业环境,人员信息安全问 ...