1. MFT介绍

Managed File Transfer (“MFT”)是一种安全的数据传输软件,是通过网络从一台计算机到另一台计算机的数据传输。

大文件传输(MFT)是一种安全的数据传输软件,是通过网络从一台计算机到另一台计算机的数据传输。MFT软件通常基于FTP网路协议。而且,MFT也可弥补FTP的缺陷。

2. 业务背景

2.1 业务流程

做的项目需要与A银行系统对接,在文件传输这块,A银行用的是MFT这种方式,并且做了一定程度的封装。大致流程是:

2.2 文件上传

  1. 我们需要在我们服务器上搭建MFT的客户端,A银行会给我们分配一个 USERID ,这个UESRID会指向A银行在自己MFT服务器上为我们分配的文件目录;

  2. 在本地服务器上创建上传目录,将要上传的文件放在该目录下;

  3. 执行A银行提供的shell脚本,上传脚本内容如下

    /home/Axway/Synchrony/SecureClient/sclient script /home/Axway/Synchrony/SecureClient/put
    
    • 1

    前面脚本都是固定的(MFT客户端安装目录,可配置成环境变量),核心在于put文件(路径可自定义),put文件示例:

    open ABank
    lcd /home/qy_work/cebfile/upload
    cd USERID
    newjob
    put 20181107.txt
    jobsubmit
    close
    

    其中 /home/qy_work/cebfile/upload 是文件上传目录,USERID为银行分配的唯一标识,20181107.txt是需要上传的文件,这里可以上传多个文件;

  4. 上传后返回信息:

    Checking transfer engine status on port 1717: is running
    open cebbank
    Connected
    lchdir /home/qy_work/cebfile/upload
    current working directory: /home/qy_work/cebfile/upload
    chdir USERID
    Directory changed
    newjob
    put 20181107.txt
    inserted in current job
    jobsubmit
    Job submitted: 20
    Close
    Disconnected
    

    这里需要注意的是Job submitted: 20,这里称为JOBID,用来查询上传状态;

  5. 查询上传文件状态信息:

    /home/Axway/Synchrony/SecureClient/sclientadm displayjob -id JOBID
    
    • 1
  6. 查询上传文件状态返回信息:

    Ident                            = 20
    Description                      =
    Site Alias                       = ABank
    Creation Date                    = 2018/11/07 16:25:59
    Start Date                       = 2018/11/07 16:25:59
    End Date                         = 2018/11/07 16:25:59
    Status                           = Finished
    Error Message                    =
    Percent                          = 100 %
    Total size                       = 20 B (20 bytes)
    Tasks count                      = 1
    Current Task                     = 0
    Connection Retry Count           = 0
    Transfer Retry Count             = 0
    Stop On Error                    = false
    Update Frequency                 = 5000
    

    重点在于 statuspercent两个字段对应信息,前者标识文件上传状态,后者标识文件上传百分比。

    至此,基于MFT文件上传的流程全部描述完。接下来说说文件下载的流程;

2.3 文件下载

  1. 文件下载同样也需要执行A银行提供的脚本,下载脚本如下:

    /home/Axway/Synchrony/SecureClient/sclient script /home/Axway/Synchrony/SecureClient/get
    
    • 1

    前面脚本都是固定的(MFT客户端安装目录,可配置成环境变量),核心在于get文件(路径可自定义),get文件示例:

    open cebbank
    lcd /home/qy_work/cebfile/download
    cd USERID
    newjob
    get 2018110702.txt
    jobsubmit
    close
    

    可以发现,和put脚本区别主要在于putget命令区别,其中 /home/qy_work/cebfile/download是文件下载目录,USERID为银行分配的唯一标识,20181107.txt是需要下载的文件,这里可以下载多个文件;

  2. 下载后返回信息:

    Checking transfer engine status on port 1717: is running
    open ABank
    Connected
    lchdir /home/qy_work/cebfile/download
    current working directory: /home/qy_work/cebfile/download
    chdir USERID
    Directory changed
    newjob
    get 2018110702.txt
    inserted in current job
    jobsubmit
    Job submitted: 23
    Close
    Disconnected
    

    这里需要注意的是Job submitted: 20,这里称为JOBID,用来查询下载状态;

  3. 查询上传文件状态信息:

    /home/Axway/Synchrony/SecureClient/sclientadm displayjob -id JOBID
    
    • 1
  4. 查询上传下载状态返回信息:

    Ident                            = 23
    Description                      =
    Site Alias                       = ABank
    Creation Date                    = 2018/11/07 17:30:14
    Start Date                       = 2018/11/07 17:30:14
    End Date                         = 2018/11/07 17:30:14
    Status                           = Finished
    Error Message                    =
    Percent                          = 100 %
    Total size                       = 20 B (20 bytes)
    Tasks count                      = 1
    Current Task                     = 0
    Connection Retry Count           = 0
    Transfer Retry Count             = 0
    Stop On Error                    = false
    Update Frequency                 = 5000
    

    重点在于 statuspercent两个字段对应信息,前者标识文件下载状态,后者标识文件下载百分比。

    到这里整个文件上传和下载的流程以及整个上传下载的过程已经全部走通。但是这是基于Linux下执行脚本来上传和下载文件。现在需要把这些过程转换成java代码。

3. 业务难点

  • put、get脚本不是固定的,需要传入文件路径、文件名称以及用户ID,其中用户ID可能是唯一的,文件路径和文件名称需要灵活配置;
  • java操作shell脚本;
  • java接收shell脚本执行后的流,并转成字符流,截取相应的上传、下载状态来判定文件上传、下载的最终状态;

4. 技术方案

4.1 脚本生成

对于put、get脚本生成,这里采用静态模板Velocity技术,动态生成put/get脚本。

4.1.1 添加依赖

 <!-- 模板引擎 --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.0</version></dependency>

4.1.2 脚本模板

MFTModel.vm

open cebbank
lcd $!{dirPath}
cd $!{userId}
newjob
$!{manageType} $!{fileName}
jobsubmit
close

4.1.3 生成脚本的工具类

package com.ceb.mental.util;import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;import java.io.*;public class VelocityUtil {private final static String CHARSET = "utf8";/*** 生成MFT 上传、下载脚本** @param manageType 上传或下载 put/get* @param dirPath    上传文件所在文件夹或下载文件存放文件夹* @param fileName   上传文件名称或下载文件名称* @param dest       生成脚本存放路径(文件夹+文件名称)* @param userId     银行分配的id* @param encode     编码格式*/public static String createMFTCommandFile(String manageType,String dirPath,String fileName,String dest,String userId,String encode) {FileOutputStream outStream = null;BufferedWriter sw = null;try {VelocityEngine ve = new VelocityEngine();ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());ve.init();Template t = ve.getTemplate("MFTModel.vm", encode);VelocityContext ctx = new VelocityContext();ctx.put("dirPath", dirPath);ctx.put("userId", userId);ctx.put("fileName", fileName);ctx.put("manageType", manageType);//确定静态文档在共享文件目录的完整存储路径File file = new File(dest);if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}outStream = new FileOutputStream(file);OutputStreamWriter oswriter = new OutputStreamWriter(outStream, encode);sw = new BufferedWriter(oswriter);t.merge(ctx, sw);sw.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (sw != null) {sw.close();}if (outStream != null) {outStream.close();}} catch (IOException e) {e.printStackTrace();}}return dest;}/*** 生成MFT 上传脚本** @param manageType 上传或下载 put/get* @param dirPath    上传文件所在文件夹或下载文件存放文件夹* @param fileName   上传文件名称或下载文件名称* @param dest       生成脚本存放路径(文件夹+文件名称)* @param userId     银行分配的id*/public static String createMFTCommandFile(String manageType,String dirPath,String fileName,String dest,String userId) {return createMFTCommandFile(manageType, dirPath, fileName, dest, userId, CHARSET);}public static void main(String[] args) throws IOException {System.out.println(createMFTCommandFile("put", "/home/qy_work/cebfile/upload","20181107.txt", "D:/file/put01", "USERID"));}
}

4.2 执行脚本

4.2.1 java执行Shell命令介绍

每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时环境。 java执行shell命令介绍
应用程序不能创建自己的Runtime类实例。
介绍几个主要方法:

  • Process exec(String command)
    ​ 在单独的进程中执行指定的字符串命令。
  • Process exec(String command, String[] envp)
    ​ 在指定环境的单独进程中执行指定的字符串命令。
  • Process exec(String command, String[] envp, File dir)
    ​ 在有指定环境和工作目录的独立进程中执行指定的字符串命令。
  • Process exec(String[] cmdarray)
    ​ 在单独的进程中执行指定命令和变量。
  • Process exec(String[] cmdarray, String[] envp)
    ​ 在指定环境的独立进程中执行指定命令和变量。
  • Process exec(String[] cmdarray, String[] envp, File dir)
    ​ 在指定环境和工作目录的独立进程中执行指定的命令和变量。
    command:一条指定的系统命令。
    envp:环境变量字符串数组,其中每个环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为null。
    dir:子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为null。
    cmdarray:包含所调用命令及其参数的数组。

4.2.2 执行shell命令后会返回inputStream

例如:

public class Test {  public static void main(String[] args){  InputStream in = null;  try {  Process pro = Runtime.getRuntime().exec(new String[]{"sh",  "/home/test/test.sh","select admin from M_ADMIN",  "/home/test/result.txt"});  pro.waitFor();  in = pro.getInputStream();  BufferedReader read = new BufferedReader(new InputStreamReader(in));  String result = read.readLine();  System.out.println("INFO:"+result);  } catch (Exception e) {  e.printStackTrace();  }  }
}

此时通过pro.getInputStream(); 获取inputstream,再将流转成字符流,此时便能输出执行shell命令后返回的信息;

4.2.3 结合业务场景的工具类

package com.ceb.mental.util;import org.apache.commons.lang.StringUtils;import java.io.BufferedReader;
import java.io.InputStreamReader;public class RunShell {private final static String BASH_PATH_PUT = "/home/Axway/Synchrony/SecureClient/sclient script ";private final static String BASH_PATH_STATUS = "/home/Axway/Synchrony/SecureClient/sclientadm displayjob -id ";private final static String GET = "get";private final static String PUT = "put";/*** MFT上传文件** @param dirPath  上传文件目录* @param fileName 上传文件名称* @param dest     上传脚本存放路径* @param userId   光大分配id* @return*/public static boolean putMFTFile(String dirPath, String fileName, String dest, String userId) {return manageMFTFile(dirPath, fileName, dest, userId, PUT);}/*** MFT下载文件** @param dirPath  下载文件存放的目录* @param fileName 下载文件名称* @param dest     下载脚本存放路径* @param userId   光大分配id* @return*/public static boolean getMFTFile(String dirPath, String fileName, String dest, String userId) {return manageMFTFile(dirPath, fileName, dest, userId, GET);}public static boolean manageMFTFile(String dirPath, String fileName, String dest, String userId, String manageType) {//生成put文件String commandFile = VelocityUtil.createMFTCommandFile(manageType, dirPath, fileName, dest, userId);//组装put脚本String command = BASH_PATH_PUT + commandFile;System.out.println("==========>执行脚本:" + command);//执行put上传命令String result = runCommand(command, 12);if (StringUtils.isNotBlank(command)) {//截取jobIdString jobId = result.substring(result.lastIndexOf(":") + 1).trim();System.out.println("截取的jobId:" + jobId);//查询状态String statusCommand = BASH_PATH_STATUS + jobId;System.out.println("==========>查询文件状态脚本:" + statusCommand);String statusResult = runCommand(statusCommand, 7);String status = statusResult.substring(statusResult.lastIndexOf("=") + 1).trim();System.out.println("上传结果:" + status);if (StringUtils.isNotBlank(status) && status.equals("Finished")) {return true;}}return false;}/*** 运行脚本,并读取特定行信息** @param commond  shell脚本* @param readLine 从第几行读取* @return*/private static String runCommand(String commond, int readLine) {String result = null;try {Process ps = Runtime.getRuntime().exec(commond);ps.waitFor();BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));StringBuffer sb = new StringBuffer();int iLine = 1;String line;while ((line = br.readLine()) != null) {if (iLine == readLine) {sb.append(line).append("\n");}iLine++;}result = sb.toString();System.out.println(result);} catch (Exception e) {e.printStackTrace();}return result;}}

4.2.4 业务测试

编写controller.

package com.ceb.mental.controller;import com.ceb.mental.util.RunShell;
import com.ceb.mental.util.VelocityUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/mft")
public class MFTController {@RequestMapping("/upload")public void putFile(String fileName){RunShell.putMFTFile("/home/qy_work/cebfile/upload", fileName,"/home/qy_work/cebfile/upload/put", "USERID");}@RequestMapping("/download")public void getFile(String fileName){RunShell.getMFTFile("/home/qy_work/cebfile/download", fileName,"/home/qy_work/cebfile/upload/get", "USERID");}}

将项目部署到MTF的客户端,访问相应的URL,

4.2.5 检查是否上传成功

/home/Axway/Synchrony/SecureClient/sclient cebbank list USERID
  • 1

这里查询的是银行MTF端上传文件的列表。查询结果,如图:

5. 总结

刚开始都不知道MFT是啥,然后从搭建客户端,在客户端一点点尝试操作,查阅相关资料,摸清原理,理清业务及其中的技术点,评估技术方案,积跬步、解决bug,最终完成了这个看似很难的需求。

生命不息、战斗不止!

基于MFT文件上传和下载相关推荐

  1. java实现基于AmazonS3文件上传、下载、删除操作

    1.创建工具类 AwsS3Utils import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientExcept ...

  2. Struts2.3.5+Hibernate3+Spring3.1基于注解实现的多文件上传,下载

    Struts2.3.5+Hibernate3+Spring3.1基于注解实现的的多文件上传,下载,这里是上传文件到数据库中,上传控件可以增加和删除,有需要的朋友可以看看. 以下是源码下载地址:http ...

  3. linux的常用操作——基于ftp的windows10和腾讯云centos操作系统之间的文件上传和下载

    \qquad在腾讯云服务器的centos操作系统上,安装vsftpd并进行配置,然后基于ftp实现windows10操作系统和腾讯云centos系统之间的文件上传和下载. 文章目录 1.基于腾讯云服务 ...

  4. Mr.张小白(案例:基于Spring MVC实现文件上传和下载)

    基于Spring MVC实现文件上传和下载 一.步骤 1.引入相关依赖pom.xml <?xml version="1.0" encoding="UTF-8&quo ...

  5. 基于FTP协议实现文件上传与下载

    目录 一.FTP简介 二.关于FTP服务器 三.文件上传 分步讲解: 完整实现代码: 四.下载文件 分步讲解: 完整实现代码: 小结 一.FTP简介 FTP(File Transfer Protoco ...

  6. WSE3.0构建Web服务安全(4):MTOM消息传输优化和文件上传、下载

    MTOM消息优化传输机制主要应用于大量数据的传输,很多文章中也直接得出结论:使用MTOM文件传输效率高.为什么MTOM的数据传输效率会比别的方式要高?MTOM真的如此完美吗,它有什么不足?什么情况下使 ...

  7. 科普|不同协议下远程服务器文件上传_下载优劣对比

    作为一个程序员,如果不知道如何进行远程服务器的文件上传与下载,实在是一件尴尬的事情.打开百度,搜索「远程服务器 上传下载」,你能得到 63,100,000 个搜搜结果,五花八门的操作方式的让人眼花缭乱 ...

  8. python实现文件上传和下载_[Python] socket实现TFTP上传和下载

    一.说明 本文主要基于socket实现TFTP文件上传与下载. 测试环境:Win10/Python3.5/tftpd64. tftpd下载:根据自己的环境选择下载,地址 :http://tftpd32 ...

  9. JavaWeb学习总结(五十)——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

最新文章

  1. LINUX常用命令(基础)
  2. mysql5.6cmd中代码_Mysql5.6.22源代码安装
  3. 基于uml的系统分析的网上商城_UML建模工具Enterprise Architect最新版有哪些新功能呢?立即查看...
  4. 手动创建DataTable并绑定gridview
  5. 为什么D触发器需要建立时间与保持时间
  6. MQTT-SN协议乱翻之实现要点
  7. python怎么改字体_python,tkinter_Tkinter Label 如何改变Label中的文字样式,例如给文字加删除线,python,tkinter - phpStudy...
  8. 20165230 《Java程序设计》实验五《网络编程与安全》实验报告
  9. SpringCloud之Zuul网关
  10. 计算机打音乐光辉岁月,光辉岁月(完美版)
  11. word文档字体段落文档格式标准设置(个人)
  12. MinGW-w64 离线包安装方法
  13. 你知道几个中文编程语言,快来瞧瞧这些有趣的中文编程语言。
  14. Floor报错注入原理解析心得
  15. 成都拓嘉启远:拼多多开店怎样节约物流成本
  16. poi 操作 导出excel 合并列
  17. 技术分享1: jinkens构建Android工程,并上传到蒲公英平台
  18. ChatGPT会对未来5年的NLP算法从业者带来怎样的冲击?
  19. BZOJ3786 星际探索
  20. Python-字典学习笔记(完)

热门文章

  1. 程序员的算法趣题Q29: 合成电阻的黄金分割比
  2. 最优化理论c语言代码,《统计学习导论基于R应用》PDF代码导图+《最优化理论与算法第2版》PDF习题指导...
  3. 《区块链技术与应用》北大肖臻老师——课程笔记【1-3】
  4. openedx搭建(汉化版)
  5. cocos2dx卡牌翻转效果
  6. Linux中文件替换命令
  7. 文章向大家介绍安卓逆向,解决app抓包抓不到的问题,主要包括安卓逆向,解决app抓包抓不到的问题使用实例、应用技巧
  8. 微信支付v2开发(9) 标记客户投诉处理状态
  9. 拼接大屏数据展示_大屏数据可视化设计注意事项
  10. DN-DETR调试记录