由于项目需要,于是又想起之前看过的设计模式,于是便有了一键导出的想法。
思路简单明了。一步一步看下去就好。
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();
}
}
此组合对象,可以是文件夹对象,也可是具体的文件对象,再后面调用中,不需要了解到底是一个文件夹还是一个文件(即组合模式的透明性)。
上述抽象类的实现如下:
public class ZipFileItem extends FileComponent{
//输入文件的路径
String inPath;
//输出文件的路径
String outPath;
//子节点文件信息
List fileComponents = new ArrayList();
//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 iterator = fileComponents.iterator();
//如果是文件夹,那么还可以迭代文件及对象中的具体文件对象
while (iterator.hasNext()) {
FileComponent fileComponent = iterator.next();
fileComponent.mkFile();
}
}
}
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; inew 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);
}
}
}
}
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();
}
}
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