批量处理1——文件的上传(bootstrap+Ajax+SSM)
批量处理2——Java花式处理EXCEL
批量处理3——Excel文件导出
批量处理4——java处理压缩文件
Java知多少——相对路径和绝对路径
HTTP知多少——Content-disposition(文件下载)
如何对ZIP压缩文件进行处理?
1. 前端处理
即使我们使用了accept="aplication/zip"
属性。但用户依旧可以选择其他格式的文件,所有我们需要在JS中进一步限制。
function batchSubmit() {
var self = $('#batchButton');
if (self.hasClass("disabled")) return;
var fileName = new String($('#batchFile').val());
if(fileName == null || fileName == '') {
layer.alert("请选择文件!", {icon: 2});
return;
}
/*校验文件是否是ZIP格式*/
if(!fileName.endWith(".zip")) {
layer.alert("请选择zip文件!", {icon: 2});
return;
}
/*使用formData完成文件上传*/
var formData = new FormData();
formData.append("KHSQ", document.getElementById("batchFile").files[0]);
$.ajax({
url: "./XXX/upload",
type: "POST",
data: formData,
contentType: false,
processData: false,
success: function (data) {
}
});
2. 文件上传
将前端上送的文件保存到服务器指定的路径上。使用
multipartFile.transferTo(new File(batchPath));
方法保存文件。
@RequestMapping("/upload")
@ResponseBody
public ResponseVo upload(HttpServletRequest request, HttpServletResponse response) {
ResponseVo responseVo = new ResponseVo();
try{
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile multipartFile = multipartRequest.getFile("KHSQ");
if(multipartFile!=null){
// 获得文件名:
String originalfilename = multipartFile.getOriginalFilename();
//文件校验TODO
String batchPath ="XXX/originalfilename";
//创建目录
File store = new File(batchPath);
if (!store.exists()) {
store.mkdirs();
}
/*保存文件*/
multipartFile.transferTo(new File(batchPath));
}
responseVo.setRetcode(200);
responseVo.setMessage("上传成功");
}catch (Exception e){
responseVo.setRetcode(400);
responseVo.setMessage("上传失败 原因:" + e.getMessage());
logger.error("上传失败 原因:" + e);
}
return responseVo;
3. 文件处理
3.1 ZIP解压缩
将ZIP文件解压缩。本质是重建一颗目录树。采用的是前序遍历的方式。当然我们采用
zipFile.getEntries();
获取Enumeration
对象,进行遍历。需要注意的是,父级目录可操纵子级目录。我们采用一个list集合,将压缩文件内的第一层目录保存到List中。
public static List upZipFilesDic(String path) {
if(StringUtils.isBlank(path)){
return null;
}
File source=new File(path);
//获取压缩文件名
String descDir=path.substring(0,path.lastIndexOf("."));
//保存第一层文件或目录
List list = new ArrayList<>() ;
//此类用于从zip文件读取条目。
ZipFile zipFile = null;
try {
//解决文件名中文乱码
zipFile = new ZipFile(source , "GBK") ;
//遍历ZIP压缩文件的条目的枚举
for(Enumeration entries = zipFile.getEntries(); entries.hasMoreElements() ; ){
//此类用于表示ZIP文件条目(目录|文件)
ZipEntry entry = (ZipEntry)entries.nextElement() ;
//获取条目的名称
File file = new File(descDir + File.separator + entry.getName()) ;
//判断条目是否是目录
if( entry.isDirectory() ){
//File.getName获取路径名称序列中的最后一个名字
String current = source.getName().substring(0,source.getName().lastIndexOf("."));
//判断该目录是否是压缩文件的第一层目录;即条目的父文件的名称==压缩文件的名字?
if(file.getParentFile().getName().equalsIgnoreCase(current)){
//将第一层目录保存到List集合中。
list.add(file);
}
}else{
//条目是文件的情况下
//获取条目的后缀名
String entityFileSuffix = file.getName().substring(file.getName().lastIndexOf(".")+1);
//获取文件的父级目录
File parent = file.getParentFile() ;
//创建目录
if( !parent.exists() ){
parent.mkdirs() ;
}
//返回用于读取指定zip文件条目内容的输入流。
InputStream in = zipFile.getInputStream(entry);
//获取文件输出流,输出到条目路径
OutputStream out = new FileOutputStream(file) ;
int len ;
while( (len = in.read(_byte)) > 0){
out.write(_byte, 0, len);
}
if (null !=out){
out.close();
}
if (null !=in){
in.close();
}
//判断后缀是否是xlsx,如果是的话,也保存到list中
if(entityFileSuffix.equalsIgnoreCase("xlsx")){
list.add(file);
}
}
}
}catch(IOException e){
logger.error(e);
}finally {
if(zipFile != null){
try{
zipFile.close();
}catch(IOException e){
logger.error(e);
}
}
}
return list;
}
处理完毕之后,只有压缩文件内的第一层目录和.xlsx后缀的文件保存到list集合中,并且zip文件完成解压。
3.2 处理解压文件
文件解压后,顶级目录和Excel文件保存到了List中。需要单独对List中目录和文件进行处理。
List fileList = GzipUtil.upZipFilesDic(path);
//保存List中的目录;
LinkedList directoryList = new LinkedList<>();
//处理Excel文件
for (File file: fileList){
String fileSuffix= file.getName().substring(file.getName().lastIndexOf(".") + 1);
if(!fileSuffix.equals("xlsx")){
//将目录保存到LinkedList中
directoryList.add(file);
}else{
//处理Excel文件
}
}
//File.listFiles()表示该抽象路径名表示的目录中的文件。
for (File file : directoryList.get(0).listFiles()){
//处理目录下的文件或目录
}
需要注意的一点是:
listFiles
能够获取当前文件夹下的所有文件和文件夹,如果文件夹A下还有文件D,那么D也在里面。
4. 压缩文件的下载
压缩文件的下载,还是设置响应报文头(Content-Disposition以及Content-Type)。
//文件路径,response,下载的文件名
public static void downloadZip(String down, HttpServletResponse response,String fileName) {
try {
// 输入流
InputStream fis = new BufferedInputStream(new FileInputStream(down));
byte[] buffer = new byte[fis.available()];
//将数据读到buffer数组中
fis.read(buffer);
fis.close();
// 清空response
response.reset();
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
//以流的形式传输
response.setContentType("application/octet-stream");
//如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
//将数据写到输出流中
toClient.write(buffer);
toClient.close();
} catch (IOException ex) {
logger.error(ex.getMessage());
}
}