Java实现对文本文件MD5加密并ftp传送到远程主机目录

需求描述:

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

客户出完账之后需要把出账的数据以文本文件的方式传送给收入管理系统,客户以前是通过本地的一个工具软件上传的,由于安全监管的原因,不允许在本地使用工具上传,因此客户希望我们在已经上线使用的系统开发一个功能实现他们的需求。

业务梳理:

我梳理一下具体的细节,具体的流程如图所示:


程序实现:

一、首先是设计页面,由于是在原系统的基础上新增功能,需要提前做好菜单的配置工作。我设计的页面如下图,一个是下拉选择框(用户选择相对应的业务),一个是选择文件,一个是月份(表示需要传送的文件是哪个月),一个是上传按钮,用户选择文件之后选择月份点击上传按钮之后即可触发上传操作。


以下是JSP界面的源码:

<%@ include file="/common/taglibs.jsp"%>

<%@ page language="java" pageEncoding="UTF-8"%>

<%@ page isELIgnored="false"%>

<s:form  enctype="multipart/form-data" method="post" onsubmit="return valid();">

<page:applyDecorator name="simpleQuery">

<table cellspacing="1" border="0">

<title><s:text name="erp接口上传小程序" /></title>

<s:hidden name="fileName"></s:hidden> 

<tr><td>业务类型

    <select id="" name="OperationType" class="formselect">

    <option></option>

    <option value="1">集团预出账</option>

    <option value="2">集团正式出账</option>

    </select>

</td>

<td>接口月份:

<as:datepicker id="startDate" name="rpmonth" readonly="false" disabled="false"

formatFlag="date6" showDefault="true" cssClass="required validate-datetime">    </as:datepicker>

</td>     

</tr>

<tr><td width="10%">选择文件

<s:file id="upload" name="upload"></s:file>

</td>

<td >

&nbsp;

</td>

<td >

<input id="impbut" type="button" value="上传" onclick="importHandle()" class="button" />

</td>                                             

</tr>

</table>

</page:applyDecorator>   

</s:form> 

<script type="text/javascript">

function importHandle() {

var fileName = $('upload').value; 

if (fileName == null || fileName == undefined || fileName == "") {

    validation.userDefined("请选择要上传的文件");

    return;

    }

    fileName = fileName.split(".");

if (fileName[fileName.length - 1] == "txt" || fileName[fileName.length - 1] == "TXT") {

    document.forms[0].action = "interfaceupload_UPLOAD_interfaceupload.do";

    document.forms[0].submit();

    } else {

    validation.userDefined("文件格式错误,您上传的格式不被允许");

    return;

    }

}

</script>

二、点击上传按钮之后的函数为:importHandle(),提交的请求为interfaceupload_UPLOAD_interfaceupload.do

<input id="impbut" type="button" value="上传" onclick="importHandle()" class="button" />

系统是由struts2实现的,因此要在配置中加入这一段请求相对应的action的配置

<!-- erp接口文件上传 -->

<action name="interfaceupload_UPLOAD_interfaceupload"

class="aicu.application.mps.voice.international.web.revenue.FileImportAction">

<result name="success">/WEB-INF/jsp/revenue/interfaceupload.jsp</result>

<param name="uploadServiceId">interfaceupload</param>

</action> 

三、做好了相对应的准备工作,继续来写接下来的业务逻辑。

编写aicu.application.mps.voice.international.web.revenue.FileImportAction类

package aicu.application.mps.voice.international.web.revenue;     

import aicu.application.mps.voice.international.web.revenue.FileUploadAction;

public class FileImportAction extends FileUploadAction {   

    public String execute() throws Exception {

        System.out.println("hello");

        smartUpload();

        return SUCCESS;

    }

}

由于FileImportAction继承了FileUploadAction,所以相对应的请求都会由>FileUploadAction的execute()来处理。

首先是获取上传上来的文件对象,通过声明上传文件的对象,内容类型,文件名,服务ID,然后在生成set()方法和get()方法便能获取到文件对象。

protected File upload;// 实际上传文件

protected String uploadContentType; // 文件的内容类型

protected String uploadFileName; // 上传文件名

protected String uploadServiceId;//上传服务ID

public File getUpload() {

    return upload;

    }

public void setUpload(File upload) {

    this.upload = upload;

    }

public String getUploadContentType() {

    return uploadContentType;

    }

public void setUploadContentType(String uploadContentType) {

    this.uploadContentType = uploadContentType;

    }

public String getUploadFileName() {

    return uploadFileName;

    }

public void setUploadFileName(String uploadFileName) {

    this.uploadFileName = uploadFileName;

    }

public String getUploadServiceId() {

    return uploadServiceId;

    }

public void setUploadServiceId(String uploadServiceId) {

    this.uploadServiceId = uploadServiceId;

    }

然后是对当前的文本文件进行MD5加密,生成同名的MD5文件,文件中只有一行加密之后的MD5字符串。

由于通过struts上传的文件是存放在临时目录下,我处理的思路是,先把文件copy到指定的路径下

String datapath = getRealPath()+"upload"+File.separator+UUID.randomUUID()+File.separator;

File newFile=new File(new File(datapath),uploadFileName);

if (!newFile.getParentFile().exists())

    newFile.getParentFile().mkdirs();

FileUtils.copyFile(upload, newFile);

然后是生成MD5同名文件

FileMD5 filemd5=new FileMD5();

String md5str=filemd5.getMD5(newFile);

实现的思路是调用byteToHexString方法得到加密之后MD5的字符串,通过writeFileContent实现把文本写入同名的MD5文件中。FileMD5类的getMD5(File file)方法:

  public  String getMD5(File file) {

    Boolean bool = false;

    FileInputStream fis = null;

    String filename=file.getName();

    String[] newfilepath=filename.split("\\.");

    String filenameTemp = file.getParent()+file.separator+newfilepath[0]+ ".md5";


    File md5file = new File(filenameTemp);

    try {

      MessageDigest md = MessageDigest.getInstance("MD5");

      fis = new FileInputStream(file);

      byte[] buffer = new byte[2048];

      int length = -1;

      long s = System.currentTimeMillis();

      while ((length = fis.read(buffer)) != -1) {

      md.update(buffer, 0, length);

      }

      byte[] b = md.digest();

      String filecontent=byteToHexString(b);

      if (!md5file.exists()) {

      md5file.createNewFile();

      bool = true;

      System.out.println("success create file,the file is "

        + md5file.getName());

      writeFileContent(filenameTemp, filecontent);

      }

      else {

      md5file.delete();

      System.out.println("success delete file,the file is "

        + md5file.getName());

      md5file.createNewFile();

      bool = true;

      System.out.println("success create file,the file is "

        + md5file.getName());

      writeFileContent(filenameTemp, filecontent); 

      }

      return byteToHexString(b);

    } catch (Exception ex) {

      ex.printStackTrace();

      return null;

    } finally {

      try {

      fis.close();

      } catch (IOException ex) {

      ex.printStackTrace();

      }

    }

      }

byteToHexString方法,主要是实现对文本文件的MD5加密,得到加密之后的MD5文件

  private  String byteToHexString(byte[] tmp) {

    String s;

    char str[] = new char[16 * 2];

    int k = 0;

    for (int i = 0; i < 16; i++) { 

      byte byte0 = tmp[i];

      str[k++] = hexdigits[byte0 >>> 4 & 0xf];   

      str[k++] = hexdigits[byte0 & 0xf];

      }

      s = new String(str);

      return s;

      }

writeFileContent方法,实现把文本写入同名的MD5文件中

  public  boolean writeFileContent(String filepath, String newstr) throws IOException {

    Boolean bool = false;

          //String filein = newstr + "\r\n";

    String filein = new String(newstr);

    String temp = "";

    FileInputStream fis = null;

    InputStreamReader isr = null;

    BufferedReader br = null;

    FileOutputStream fos = null;

    PrintWriter pw = null;

    try {

        File file = new File(filepath);

        fis = new FileInputStream(file);

        isr = new InputStreamReader(fis);

        br = new BufferedReader(isr);

        StringBuffer buffer = new StringBuffer();

          for (int i = 0; (temp = br.readLine()) != null; i++) {

              buffer.append(temp);

              buffer = buffer.append(System.getProperty("line.separator"));

              }

              buffer.append(filein);

              fos = new FileOutputStream(file);

              pw = new PrintWriter(fos);

              pw.write(buffer.toString().toCharArray());

              pw.flush();

              bool = true;

          } catch (Exception e) {

              e.printStackTrace();

          } finally {

              if (pw != null) {

                  pw.close();

              }

              if (fos != null) {

                  fos.close();

              }

              if (br != null) {

                  br.close();

              }

              if (isr != null) {

                  isr.close();

              }

              if (fis != null) {

                  fis.close();

              }

          }

          return bool;

      }

四、获取到文本文件和生成同名的文件名之后,紧接着就是获取相对应的ftp主机,用户名,密码以及路径信息了。我把这相对应的信息保存在数据库中。首先我们把获取到的业务类型放入一个HashMap中。

  parameterMap=new HashMap();

  parameterMap.put("audit_flag",OperationType);

然后我们配置ibaits的sqlid

  <!-- 根据业务选择路径,zhongfs于2017-12-05添加 -->

  <select id="checkFtpType" resultClass="java.util.LinkedHashMap">

  select ftphost, proguser, progpass, remotedirectory from t_ftp_config s

  where 1 = 1

  <isNotEmpty prepend="AND" property="audit_flag">

  <![CDATA[   

  s.audit_flag = #audit_flag#

  ]]>

  </isNotEmpty>

  </select>

然后执行该sqlid的查询,把结果放入List 中

List<Map> resultType=EasyDataFatcherOnIbatis.queryBySqlKey("checkFtpType",false,parameterMap);

下面是根据该sqlid查询出来的List结果中,取出相关的信息

String host = (String)resultType.get(0).get("FTPHOST");

String user = (String)resultType.get(0).get("PROGUSER");

String pass = (String)resultType.get(0).get("PROGPASS");

String path = (String)resultType.get(0).get("REMOTEDIRECTORY");   

//每月会自动生成一个月份的子目录

String relpath=path+rpmonth+"/";

至此,便可以获取到相对应的ftp主机,用户名,密码以及路径信息了。

五、最后一步是实现上传,我是用的FTPClient来实现的。

实现的操作都写在了FtpBBSUtil的FtpSento方法中,其中datapath表示需要传送文件的目录。

FtpBBSUtil.getFtpBBS().FtpSento(datapath, host, user, pass, relpath);

FtpBBSUtil的FtpSento方法如下所示:

  public void FtpSento(String localPath, String host, String user,

    String pass, String path) throws Exception {

    login(host, 21, user, pass);

    File parentFile = new File(localPath);

    File[] files = parentFile.listFiles();

    String outPath = path;

    for (File aFile : files) {

        if (aFile != null && aFile.getName() != null) {

            put(aFile, outPath, new String((aFile.getName())

            .getBytes("GB18030"), "ISO8859-1"));

        }

    }

    logout();

  }

总结

本篇文章描写了Java如何实现对某一目录下的文件夹下的文本文件实现MD5加密,并生成同名的MD5文件,根据配置信息,获取主机ip,用户名密码,传送的路径,然后实现ftp远程传送功能。如果你有类似的需求,希望可以帮助到你,或者你能从中获取到灵感。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。 

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容