项目架构:spring+struts2+hibernate4+oracle
需求:用户导入excel文件,导入到相应的数据表中,要求提供导入模板,支持xls和xlsx文件
思路分析:
1、提供一个下载链接,点击下载,可以使超链接,src直接是项目路径加文件名。
2、通过上传文件,服务器接收上传,返回一个上传后的服务器本地路径,通过ajax异步赋值到jsp的路径隐藏域。
3、ajax异步提交导入请求,后台处理,将路径转换成File,File转换成MultipartFile,将文件读取转换成一个数组类型的集合。
4、循环集合这种的数据,每一行excel数据,是一个元素,将元素转换成相应的java对象进行保存。
一、所需jar包
一共是6个jar包。
二、前端jsp代码部分
<input type="hidden" id="excelFilePath" name="excelFilePath" value="" />
<tr>
<td>选择文件:</td>
<td><input type="file" name="uploadFile" id="excelFile"></input></input>
<span id="uploadMsg"></span></td>
</tr>
<tr>
<td></td>
<td> <input type="button" value="上传" onclick="fileUpload()">
<input type="button" value="导入" id="btnOk" disabled="true" onclick="importEmp()"/>
</td>
</tr>
<script type="text/javascript">
// 文件上传
function fileUpload(){
$("#fileTypeError").html("");
$("#btnOk").attr("disabled",true);
var fileName = $("#excelFile").val();
var fileType = fileName.substr(fileName.length-4,fileName.length);
if(fileType == ".xls" || fileType == "xlsx"){
var uploadFileUrl = "${basePath}/public/uploadFile.action";
var formData = new FormData($("#mainForm")[0]);
$.ajax({
type: "POST",
url: uploadFileUrl,
data: formData,
cache: false,
processData: false,
contentType: false,
dataType : "json",
success: function(data){
if(null != data){
if (data.dataStatus == "1") {
$("#uploadMsg").html("<font color='green'>上传成功!</font>");
$("#btnOk").attr("disabled",false);
$("#excelFilePath").attr("value",data.dataMain);
//alert($("#excelFilePath").val());
} else {
if (data.errorMsg != null
&& data.errorMsg.length > 0) {
alert(data.errorMsg);
$("#uploadMsg").html("<font color='red'>" +data.errorMsg + "请仔细阅读操作说明!</font>");
}
}
}
},
error : function(XMLHttpRequest, textStatus,
errorThrown) {
alert("系统异常[" + textStatus + "]:" + errorThrown);
}
});
}else{
$("#uploadMsg").html("<font color='red'>上传文件类型错误,支持类型: .xls .xlsx</font>");
}
}
//Excel文件导入到数据库中
function importEmp(){
var importExcelURL = "${basePath}/public/importResultExaminee.action";
var excelFilePath = $("#excelFilePath").val();
$.ajax({
type: "POST",
url: importExcelURL,
data: {"excelFilePath":excelFilePath},
cache: false,
dataType : "json",
success: function(data){
if(null != data){
if (data.dataStatus == "1") {
$("#btnOk").attr("disabled",false);
alert("本次成功导入数量:" + data.dataMain);
}else{
if (data.errorMsg != null
&& data.errorMsg.length > 0) {
alert(data.errorMsg);
}
}
}
},
error : function(XMLHttpRequest, textStatus,
errorThrown) {
alert("系统异常[" + textStatus + "]:" + errorThrown);
}
})
}
</script>
三、核心处理类POIUtils代码:
package com.sinotn.utils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
/**
* excel导出导入工具类
* Copyright (c) 2018 by Sinotn
* @author Libin
* @date 2018年4月8日 上午9:39:50
*/
public class POIUtils {
private static Logger logger = Logger.getLogger(POIUtils.class);
private final static String XLS = "xls";
private final static String XLSX = "xlsx";
/**
* 读取excel文件
* @param formFile
* @return
* @throws IOException
*/
public static List<String[]> readExcel(MultipartFile formFile) throws IOException {
// 检查文件
checkFile(formFile);
//获得Workbook工作薄对象
Workbook workbook = getWorkBook(formFile);
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
if (null != workbook) {
for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets();sheetNum++) {
//获得当前sheet工作表
Sheet sheet = workbook.getSheetAt(sheetNum);
if (null == sheet) {
continue;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环除了第一行的所有行
for (int rowNum = firstRowNum + 1;rowNum <= lastRowNum;rowNum++) {
//获得当前行
Row row = sheet.getRow(rowNum);
if(row == null){
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int lastCellNum = row.getPhysicalNumberOfCells();
String[] cells = new String[row.getPhysicalNumberOfCells()];
//循环当前行
for (int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++) {
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
}
workbook.close();
}
return list;
}
/**
* 获取当前行数据
* @param cell
* @return
*/
@SuppressWarnings("deprecation")
private static String getCellValue(Cell cell) {
String cellValue = "";
if(cell == null){
return cellValue;
}
//把数字当成String来读,避免出现1读成1.0的情况
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
cell.setCellType(Cell.CELL_TYPE_STRING);
}
//判断数据的类型
switch (cell.getCellType()){
case Cell.CELL_TYPE_NUMERIC: //数字
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING: //字符串
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: //空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: //故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
/**
* 获得Workbook工作薄对象
* @param formFile
* @return
*/
private static Workbook getWorkBook(MultipartFile formFile) {
//获得文件名
String fileName = formFile.getName();
//创建Workbook工作薄对象,表示整个excel
Workbook workbook = null;
try {
//获取excel文件的io流
InputStream is = formFile.getInputStream();
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if(fileName.endsWith(XLS)){
//2003
workbook = new HSSFWorkbook(is);
}else if(fileName.endsWith(XLSX)){
//2007
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
logger.info(e.getMessage());
}
return workbook;
}
/**
* 检查文件
* @param formFile
* @throws IOException
*/
private static void checkFile(MultipartFile formFile) throws IOException {
//判断文件是否存在
if(null == formFile){
logger.error("文件不存在!");
throw new FileNotFoundException("文件不存在!");
}
//获得文件名
String fileName = formFile.getName();
//判断文件是否是excel文件
if(!fileName.endsWith(XLS) && !fileName.endsWith(XLSX)){
logger.error(fileName + "不是excel文件");
throw new IOException(fileName + "不是excel文件");
}
}
}
四、action层代码
POIUtil.readExcel方法读取excel文件后,把一行中的值按先后顺序组成一个数组,所有的行作为一个集合返回。我们可以在代码中循环这个集合,把数组赋值到实体类对象中。
我在前台用form表单提交file文件,因为用的SpringMVC框架,后台用MultipartFile接收,代码如下:
/**
* 读取excel文件中的用户信息,保存在数据库中
* @param excelFile
*/
@RequestMapping("/readExcel")
public void readExcel(@RequestParam(value = "excelFile") MultipartFile excelFile,HttpServletRequest req,HttpServletResponse resp){
Map<String, Object> param = new HashMap<String, Object>();
List<User> allUsers = new ArrayList<User>();
try {
List<String[]> userList = POIUtil.readExcel(excelFile);
for(int i = 0;i<userList.size();i++){
String[] users = userList.get(i);
User user = new User();
user.setUserName(users[0]);
user.setPassword(users[1]);
user.setAge(Integer.parseInt(users[2]));
allUsers.add(user);
}
} catch (IOException e) {
logger.info("读取excel文件失败", e);
}
param.put("allUsers", allUsers);
this.userService.insertUsers(param);
}
调用的service层方法就不贴代码了,下面就是往数据库插入数据了。
excel文件内容: