Przeglądaj źródła

feat:【infra 基础设施】ftp、sftp 库升级与兼容

YunaiV 9 miesięcy temu
rodzic
commit
568216084e

+ 2 - 2
yudao-dependencies/pom.xml

@@ -61,7 +61,7 @@
         <transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
         <commons-net.version>3.11.1</commons-net.version>
         <commons-lang3.version>3.18.0</commons-lang3.version>
-        <jsch.version>0.1.55</jsch.version>
+        <jsch.version>2.27.3</jsch.version>
         <tika-core.version>3.2.2</tika-core.version>
         <ip2region.version>2.7.0</ip2region.version>
         <bizlog-sdk.version>3.0.6</bizlog-sdk.version>
@@ -526,7 +526,7 @@
                 <version>${commons-net.version}</version>
             </dependency>
             <dependency>
-                <groupId>com.jcraft</groupId>
+                <groupId>com.github.mwiede</groupId>
                 <artifactId>jsch</artifactId> <!-- 解决 sftp 连接 -->
                 <version>${jsch.version}</version>
             </dependency>

+ 1 - 1
yudao-module-infra/pom.xml

@@ -101,7 +101,7 @@
             <artifactId>commons-net</artifactId> <!-- 文件客户端:解决 ftp 连接 -->
         </dependency>
         <dependency>
-            <groupId>com.jcraft</groupId>
+            <groupId>com.github.mwiede</groupId>
             <artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 -->
         </dependency>
         <!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 -->

+ 17 - 4
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/ftp/FtpFileClient.java

@@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.ftp.Ftp;
+import cn.hutool.extra.ftp.FtpConfig;
 import cn.hutool.extra.ftp.FtpException;
 import cn.hutool.extra.ftp.FtpMode;
 import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient;
@@ -18,6 +19,15 @@ import java.io.ByteArrayOutputStream;
  */
 public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> {
 
+    /**
+     * 连接超时时间,单位:毫秒
+     */
+    private static final Long CONNECTION_TIMEOUT = 3000L;
+    /**
+     * 读写超时时间,单位:毫秒
+     */
+    private static final Long SO_TIMEOUT = 10000L;
+
     private Ftp ftp;
 
     public FtpFileClient(Long id, FtpFileClientConfig config) {
@@ -26,9 +36,12 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> {
 
     @Override
     protected void doInit() {
-        // 初始化 Ftp 对象
-        this.ftp = new Ftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(),
-                CharsetUtil.CHARSET_UTF_8, null, null, FtpMode.valueOf(config.getMode()));
+        // 初始化 Ftp 对象:https://gitee.com/zhijiantianya/yudao-cloud/pulls/207/
+        FtpConfig ftpConfig = new FtpConfig(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(),
+                CharsetUtil.CHARSET_UTF_8, null, null);
+        ftpConfig.setConnectionTimeout(CONNECTION_TIMEOUT);
+        ftpConfig.setSoTimeout(SO_TIMEOUT);
+        this.ftp = new Ftp(ftpConfig, FtpMode.valueOf(config.getMode()));
     }
 
     @Override
@@ -72,4 +85,4 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> {
         ftp.reconnectIfTimeout();
     }
 
-}
+}

+ 2 - 3
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/ftp/FtpFileClientConfig.java

@@ -1,11 +1,10 @@
 package cn.iocoder.yudao.module.infra.framework.file.core.client.ftp;
 
 import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
-import lombok.Data;
-import org.hibernate.validator.constraints.URL;
-
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.URL;
 
 /**
  * Ftp 文件客户端的配置类

+ 32 - 4
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/sftp/SftpFileClient.java

@@ -1,9 +1,14 @@
 package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp;
 
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.ftp.FtpConfig;
+import cn.hutool.extra.ssh.JschRuntimeException;
 import cn.hutool.extra.ssh.Sftp;
 import cn.iocoder.yudao.framework.common.util.io.FileUtils;
 import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient;
+import com.jcraft.jsch.JSch;
 
 import java.io.File;
 
@@ -14,6 +19,20 @@ import java.io.File;
  */
 public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> {
 
+    /**
+     * 连接超时时间,单位:毫秒
+     */
+    private static final Long CONNECTION_TIMEOUT = 3000L;
+    /**
+     * 读写超时时间,单位:毫秒
+     */
+    private static final Long SO_TIMEOUT = 10000L;
+
+    static {
+        // 某些旧的 sftp 服务器仅支持 ssh-dss 协议,该协议并不安全,默认不支持该协议,按需添加
+        JSch.setConfig("server_host_key", JSch.getConfig("server_host_key") + ",ssh-dss");
+    }
+
     private Sftp sftp;
 
     public SftpFileClient(Long id, SftpFileClientConfig config) {
@@ -22,18 +41,27 @@ public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> {
 
     @Override
     protected void doInit() {
-        // 初始化 Ftp 对象
-        this.sftp = new Sftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword());
+        // 初始化 Sftp 对象
+        FtpConfig ftpConfig = new FtpConfig(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(),
+                CharsetUtil.CHARSET_UTF_8, null, null);
+        ftpConfig.setConnectionTimeout(CONNECTION_TIMEOUT);
+        ftpConfig.setSoTimeout(SO_TIMEOUT);
+        this.sftp = new Sftp(ftpConfig);
     }
 
     @Override
     public String upload(byte[] content, String path, String type) {
         // 执行写入
         String filePath = getFilePath(path);
+        String fileName = FileUtil.getName(filePath);
+        String dir = StrUtil.removeSuffix(filePath, fileName);
         File file = FileUtils.createTempFile(content);
         reconnectIfTimeout();
-        sftp.mkDirs(FileUtil.getParent(filePath, 1)); // 需要创建父目录,不然会报错
-        sftp.upload(filePath, file);
+        sftp.mkDirs(dir); // 需要创建父目录,不然会报错
+        boolean success = sftp.upload(filePath, file);
+        if (!success) {
+            throw new JschRuntimeException(StrUtil.format("上传文件到目标目录 ({}) 失败", filePath));
+        }
         // 拼接返回路径
         return super.formatFileUrl(config.getDomain(), path);
     }

+ 2 - 3
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/sftp/SftpFileClientConfig.java

@@ -1,11 +1,10 @@
 package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp;
 
 import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
-import lombok.Data;
-import org.hibernate.validator.constraints.URL;
-
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.URL;
 
 /**
  * Sftp 文件客户端的配置类