使用迭代器模式和组合模式实现浏览器一键导出下载为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