需求描述:
客戶出完賬之后需要把出賬的數據以文本文件的方式傳送給收入管理系統,客戶以前是通過本地的一個工具軟件上傳的,由于安全監管的原因,不允許在本地使用工具上傳,因此客戶希望我們在已經上線使用的系統開發一個功能實現他們的需求。
業務梳理:
我梳理一下具體的細節,具體的流程如圖所示:
程序實現:
一、首先是設計頁面
由于是在原系統的基礎上新增功能,需要提前做好菜單的配置工作。我設計的頁面如下圖,一個是下拉選擇框(用戶選擇相對應的業務),一個是選擇文件,一個是月份(表示需要傳送的文件是哪個月),一個是上傳按鈕,用戶選擇文件之后選擇月份點擊上傳按鈕之后即可觸發上傳操作。
以下是jsp界面的源碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<%@ 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 > </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
1
|
<input id= "impbut" type= "button" value= "上傳" onclick= "importhandle()" class = "button" /> |
系統是由struts2實現的,因此要在配置中加入這一段請求相對應的action的配置
1
2
3
4
5
6
|
<!-- 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類
1
2
3
4
5
6
7
8
9
|
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()方法便能獲取到文件對象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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到指定的路徑下
1
2
3
4
5
|
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同名文件
1
2
|
filemd5 filemd5= new filemd5(); string md5str=filemd5.getmd5(newfile); |
實現的思路是調用bytetohexstring方法得到加密之后md5的字符串,通過writefilecontent實現把文本寫入同名的md5文件中。filemd5類的getmd5(file file)方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
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文件
1
2
3
4
5
6
7
8
9
10
11
12
|
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文件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
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中。
1
2
|
parametermap= new hashmap(); parametermap.put( "audit_flag" ,operationtype); |
然后我們配置ibaits的sqlid
1
2
3
4
5
6
7
8
9
10
|
<!-- 根據業務選擇路徑,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 中
1
|
list<map> resulttype=easydatafatcheronibatis.querybysqlkey( "checkftptype" , false ,parametermap); |
下面是根據該sqlid查詢出來的list結果中,取出相關的信息
1
2
3
4
5
6
|
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表示需要傳送文件的目錄。
1
|
ftpbbsutil.getftpbbs().ftpsento(datapath, host, user, pass, relpath); |
ftpbbsutil的ftpsento方法如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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遠程傳送功能。如果你有類似的需求,希望可以幫助到你,或者你能從中獲取到靈感。
原文鏈接:https://www.cnblogs.com/zhongfengshan/p/9396852.html