项目中遇到的一些小问题分享,希望能有更好更优的解决办法~
本次web项目中用到了apache poi3.9的API接口来实现EXCEL的导入读写功能.
protected static Logger logger = Logger.getLogger(CheckAction.class);
@RequestMapping(value = "/importExcel")
public String comnQuery(String p,@RequestParam(value="fileName",required=false) MultipartFile file,HttpServletRequest request, ModelMap model)
首先是开头,得提供一个供前台调用的入口,一般前后端交互用的ajax,这里就不再贴前台的js代码.
那么在前台用户界面通过ajax传递来的数据,我是直接通过流来获取.
获取文件流
logger.info("获取文件流");
InputStream inputStream = file.getInputStream();
获取前端界面输入的数据
Map params = new HashMap();
Enumeration pNames = request.getParameterNames();
while(pNames.hasMoreElements()){
String name = pNames.nextElement();
String value = request.getParameter(name);
params.put(name,value);
}
logger.info("获取前台参数为:{}",params);
String number=(String) params.get("number"); //数目
String amount=(String) params.get("amount"); //金额
String date=(String) params.get("date"); //日期
//.....根据前台的name获取值
因为一般情况,前台界面用户放入的文件不能保证一定是EXCEL格式的文件,所以需要对文件格式进行限制.可以再前端JS或者后台java进行限制,
前端JS的代码可以参考一下https://www.cnblogs.com/57rongjielong/p/7896977.html这篇博客
我主要介绍后台java对上传文件格式的限制方法.
第一种:根据文件内容去判断文件格式
String fileType = CheckFileTypeUtil.getFileType(uploadFilePath);
if(!".xls".equals(fileType.toLowerCase())||!".xlsx".equals(fileType.toLowerCase())){
uploadFile.delete();
throw new ErrorException("文件格式较验错误,请上传Excel文件(.xls)");
}
这是工具类的代码
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.tika.Tika;
public class CheckFileTypeUtil {
private static final Tika tika = new Tika();
private static Map fileTypes = new HashMap();
static {
// images
fileTypes.put("image/jpeg", ".jpg");
fileTypes.put("image/png", ".png");
fileTypes.put("image/gif", ".gif");
// 文档
fileTypes.put("text/plain", ".txt");
fileTypes.put("application/msword", ".doc");
fileTypes.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx");
fileTypes.put("application/vnd.ms-excel", ".xls");
fileTypes.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx");
fileTypes.put("application/pdf", ".pdf");
// 压缩包
fileTypes.put("application/zip", ".zip");// zip压缩文件
}
public static String getFileType(String path) throws IOException {
File file = new File(path);
String describe = tika.detect(file);
String fileType = "";
if (fileTypes.containsKey(describe)) {
fileType = fileTypes.get(describe);
}
return fileType;
}
public static String getFileType(MultipartFile file) throws IOException {
String describe = tika.detect(file);
String fileType = "";
if (fileTypes.containsKey(describe)) {
fileType = fileTypes.get(describe);
}
return fileType;
}
//测试方法
public static void main(String[] args) throws IOException {
String path = "F:/50000000150366589389902061985558000000014720434938999577.jpg";
File file = new File(path);
System.out.println(tika.detect(file));
}
}
第二种根据文件名去判断文件格式
String fileName = file.getName();
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
if(!".xls".equals(fileType.toLowerCase())||!".xlsx".equals(fileType.toLowerCase())){
uploadFile.delete();
throw new ErrorException("文件格式较验错误,请上传Excel文件(.xls)");
}
如果格式不符会主动中断程序提示文件格式错误,当需要上传到服务器备份时,可以参考以下代码
/**
* 上传服务器
* @param file
* @param request
* @return uploadFilePath
* @throws ErrorException
* @throws IOException
*/
public String uploadExcel(MultipartFile file, HttpServletRequest request) throws ErrorException, IOException {
// Web项目路径
String webPath = request.getSession().getServletContext().getRealPath("");
//获取上传文件名
String fileName = file.getOriginalFilename();
if(StringUtils.isEmpty(fileName)){
throw new ErrorException("请选择上传文件!");
}
//临时文件存放目录
String uploadDir = webPath + "/WEB-INF/tempfiles/";
// 当目录不存时 创建新的文件目录
File uploadFileDir = new File(uploadDir);
if (!uploadFileDir.exists()) {
uploadFileDir.mkdir();
}
//新的文件名
String shortName = CommonUtil.generateComsumeSeqNo();
String uploadFilePath = uploadDir + shortName + ".xls";
//上传文件至本地服务器
File uploadFile = new File(uploadFilePath);
try {
file.transferTo(uploadFile);
} catch (Exception e) {
logger.error("上传文件至本地服务器出错,"+e.getMessage(), e);
throw new ErrorException("上传文件至本地服务器出错");
}
//获取文件类型
String fileType = CheckFileTypeUtil.getFileType(uploadFilePath);
if(!".xls".equals(fileType.toLowerCase())||!".xlsx".equals(fileType.toLowerCase())){
uploadFile.delete();
throw new ErrorException("文件格式较验错误,请上传Excel文件(.xls)");
}
return uploadFilePath;
}
然后开始读取文件内容,但是在读取文件内容之前,我们应该先根据文件是xls还是xlsx来创建对象,所以建议跟刚刚的文件格式判断放在一起:
/**
* 解析文件
* @param list,inputStream,fileName
* @throws IOException
* @throws ThirdPayException
*/
public void readExcel(ArrayList list,InputStream inputStream,String fileName) throws IOException, ThirdPayException {
if(fileName.toLowerCase().contains("xlsx")){
//获取2016Excel工作簿对象
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
//得到Excel工作表对象,每个表格有多个sheet页,根据需求来读取相应的sheet页
XSSFSheet sheetAt = workbook.getSheetAt(0);
//循环读取表格数据
for (Row row : sheetAt) {
try{
//为了方便存储表格的内容,需要创建一个对应的对象来存储每一行的数据内容
ImportObject importObject=new ImportObject();
for (Cell cell : row) {
//读取数据前设置单元格类型
cell.setCellType(CellType.STRING);
}
//读取当前行中单元格数据,索引从0开始
importObject.setOne (row.getCell(1).getStringCellValue()); //表格数据
importObject.setTwo (row.getCell(2).getStringCellValue()); //表格数据
list.add(importObject);
}catch(Exception e){
//当表格某一行的某个值为空时,会抛出异常,这个时候可以根据需要主动捕获异常跳过该行数据
continue;
}
}
//5、关闭流
workbook.close();
}else{
//获取2007Excel工作簿对象
HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
//得到Excel工作表对象,每个表格有多个sheet页,根据需求来读取相应的sheet页
HSSFSheet sheetAt = workbook.getSheetAt(0);
//循环读取表格数据
for (Row row : sheetAt) {
try{
//为了方便存储表格的内容,需要创建一个对应的对象来存储每一行的数据内容
ImportObject importObject=new ImportObject();
for (Cell cell : row) {
//读取数据前设置单元格类型
cell.setCellType(CellType.STRING);
}
//读取当前行中单元格数据,索引从0开始
importObject.setOne ( row.getCell(1).getStringCellValue()); //表格数据
importObject.setTwo (row.getCell(2).getStringCellValue()); //表格数据
list.add(importObject);
}catch(Exception e){
//当表格某一行的某个值为空时,会抛出异常,这个时候可以根据需要主动捕获异常跳过该行数据
continue;
}
}
//5、关闭流
workbook.close();
}else{
//自定义异常类,放在下次博客中说明
throw new ThirdPayException("文件格式有误");
}
logger.info("读取文件完成");
}
这个时候数据就读取完成了,可以进行后续得数据处理和持久化操作了,在后续的数据处理中还碰到了很多问题,下次博客中会慢慢跟大家分享.