使用迭代器模式和组合模式实现浏览器一键导出下载为zip压缩包文件
由于项目需要,于是又想起之前看过的设计模式,于是便有了一键导出的想法。
思路简单明了。一步一步看下去就好。
1.创建组合对象
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
|
public abstract class filecomponent { /** * description: 递归创建文件夹,或者文件 */ public void mkfile(){ throw new unsupportedoperationexception(); } /** * description: 获取文件输入路径 */ public string getinpath(){ throw new unsupportedoperationexception(); } /** * description: 获取文件输出路径 */ public string getoutpath(){ throw new unsupportedoperationexception(); } /** * description: 对于文件夹来说是可以add其他文件夹或者文件 */ public void add(filecomponent filecomponent){ throw new unsupportedoperationexception(); } } |
此组合对象,可以是文件夹对象,也可是具体的文件对象,再后面调用中,不需要了解到底是一个文件夹还是一个文件(即组合模式的透明性)。
2.组合对象抽象类的实现
上述抽象类的实现如下:
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
|
public class zipfileitem extends filecomponent{ //输入文件的路径 string inpath; //输出文件的路径 string outpath; //子节点文件信息 list<filecomponent> filecomponents = new arraylist<filecomponent>(); //inpath 可以为null public zipfileitem(string outpath){ this .outpath =outpath; } //压缩文件的源目录路径和压缩好的目标位置 public zipfileitem(string inpath,string outpath){ this .inpath =inpath; this .outpath =outpath; } public void add(filecomponent filecomponent){ filecomponents.add(filecomponent); } public void remove(filecomponent filecomponent){ filecomponents.remove(filecomponent); } @override public string getinpath(){ return inpath; } @override public string getoutpath(){ return outpath; } @override public void mkfile(){ fileutils.createfile(inpath, outpath); iterator<filecomponent> iterator = filecomponents.iterator(); //如果是文件夹,那么还可以迭代文件及对象中的具体文件对象 while (iterator.hasnext()) { filecomponent filecomponent = iterator.next(); filecomponent.mkfile(); } } } |
3.文件工具类
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
public class conferencefileutils { /** * description: 根据文件的绝对路径,在绝对的输出路径进行创建文件 * @param inpath 输入路径,如果是要根据已有的文件来创建,那么一定要传 * @param outpath 输出路径,如果是目录则不用 */ public static void createfile(string inpath,string outpath){ file filein = new file(inpath); file fileout = new file(outpath); //如果目标文件已存在,则忽略,如果文件不存在 。则进行创建 if (!fileout.exists()) { int lastseparator = outpath.lastindexof(file.separator); string lastpart = outpath.substring(lastseparator); //如果不是文件夹,则创建文件 if (lastpart.lastindexof( "." )!=- 1 ) { loggerutil.info( "----------making concretefile--------" +outpath); fileinputstream in = null ; fileoutputstream out = null ; file directory = null ; try { directory = new file(outpath.substring( 0 , lastseparator+ 1 )); directory.mkdirs(); out= new fileoutputstream(fileout); //如果源文件存在 if (filein.exists()) { in= new fileinputstream(filein); int len; byte [] buf= new byte [ 10240 ]; while ((len=in.read(buf))> 0 ){ out.write(buf, 0 ,len); } out.close(); in.close(); in = null ; } } catch (ioexception e) { system.err.println( "creating file failed!" , e); } } //如果是文件夹则创建文件夹,如果父类文件夹不存在,那么也创建 else { system.err.println( "----------making directory--------" +outpath); fileout.mkdirs(); } } } //递归删除文件夹以及文件 public static boolean deletedir(file dir) { if (dir.isdirectory()) { string[] children = dir.list(); //递归删除目录中的子目录 for ( int i= 0 ; i<children.length; i++) { boolean success = deletedir( new file(dir, children[i])); if (!success) { return false ; } } } // 目录此时为空,可以删除 return dir.delete(); } // 输出文件对象到输出流 public static void outputfile(file file, httpservletresponse response) throws ioexception { outputstream out= null ; fileinputstream in= null ; try { byte [] src = new byte [ 1024 ]; out = response.getoutputstream(); in = new fileinputstream(file); int len= 0 ; while ((len = in.read(src)) > 0 ) { out.write(src, 0 , len); } out.flush(); out.close(); in.close(); } catch (ioexception e) { throw new ioexception(e); } finally { if ( null !=out){ fortifyutil.commonreleasedresource(out); } if ( null !=in){ fortifyutil.commonreleasedresource(in); } } } } |
4.核心导出逻辑代码
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
public class exportmaterialtoziptemplate { @resource private enrichfilelevelsservice enrichfilelevelsservice; //根目录文件夹名称 or 下载浏览器文件名 private string downloadzipname; //根目录地址 private string savepath = "d:\\tempfile" ; //根目录路径 private string superrootpath; //根目录对象 private filecomponent superroot; //业务参数dto private exportallthematerialdto paramdto; //response private httpservletresponse response; public exportmaterialtoziptemplate(exportallthematerialdto paramdto,enrichfilelevelsservice enrichfilelevelsservice,httpservletresponse response) { this .downloadzipname = paramdto.getdownloadzipname(); this .paramdto = paramdto; this .response = response; this .enrichfilelevelsservice = enrichfilelevelsservice; this .superrootpath =savepath+file.separator+downloadzipname; this .superroot = new zipfileitem(superrootpath); } //1.封装根目录 private void enrichfilelevels(){ enrichfilelevelsservice.enrichfilelevels(superroot,superrootpath,paramdto); } //2.生成文件目录层级,即创建所有的文件(包括文件夹) private void createallthefiles(){ if ( null !=superroot) { superroot.mkfile(); } } //3.生成文件层级后后再压缩后下载到浏览器 private void compressanddownload() { file srcfile = new file(fortifyutil.filterfilename(superrootpath)); string targetfilepath = savepath+file.separator+srcfile.getname()+ ".zip" ; file targetfile = new file(fortifyutil.filterfilename(targetfilepath)); zipfileutil.zipfiles(srcfile,targetfile); try { //压缩文件临时路径 string downfilename = downloadzipname+ ".zip" ; response.reset(); // 定义输出类型 response.setcontenttype( "application/octet-stream" ); response.setheader( "content-disposition" , "attachment;filename=" + new string(downfilename.getbytes( "gbk" ), "iso-8859-1" ) + ";size=" + targetfile.length()); outputfileutil.outputfile(targetfile, response); // 删除临时存放的文件夹 if (srcfile.exists()) { conferencefileutils.deletedir(srcfile); } //删除临时的压缩包 if (targetfile.exists()) { targetfile.delete(); } } catch (ioexception e) { devlog.error(e.getmessage()); } } //一键导出,外观模式 public void export() { enrichfilelevels(); createallthefiles(); compressanddownload(); } } |
5.丰富文件层级的接口
1
2
3
|
public interface enrichfilelevelsservice { public void enrichfilelevels(filecomponent superroot,string superrootpath,exportallthematerialdto paramdto); } |
不同的业务场景只要实现这接口,实现enrichfilelevels()方法,将实现此接口的
类实例传到exportmaterialtoziptemplate类的构造方法,然后调用exportmaterialtoziptemplate类实例的export()方法即可。即
new exportmaterialtoziptemplate(dtoparams,
enrichfilelevelsservice, response).export();
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/uniquewonderq/article/details/79655835