一:介绍
前端:文件上传原理便是数据的提交,比如Form表单提交、Ajax提交、Ajax提交Form表单等,有多种组合方式,根据需求
不同,使用不同的提交方式,但是原理相同。
后端:接收前端发送的数据(File),解析文件(本文为Excel),解析Excel有多种方式,如poi,还有网上的js-xlsx-master相关js,后者为一个开源项目实例,本文没有使用。
基本原理:读取Excel表,根据版本不同创建不同的Workbook;遍历所有的Sheet;遍历所有row;遍历所有cell;
row为List
以下测试开发使用Spring mvc框架,使用的包主要有commons-fileupload-1.3.3.jar和org.apache.poi包,网上有说必须要有commons-io包,因为fileupload依赖于他(因为开发为一个模块,这些包原来都有了,并没有测试)。
二、后台函数
Controller函数:该方法接收传递数据(File),调用工具类和服务层方法进行处理,分别为获取List和对数据进行处理,
本处为数据入库。如果读取为部分数据,可以:1.数据库设置默认值2.new Object时构造赋值3.插入时sql中赋值。
/**
* 数据上传导入
* @param file
* @param model
* @param request
* @param res
*/
@RequestMapping("/upload.json")
public ModelMap uploadExcel(ModelMap model,HttpServletRequest request,@RequestParam("excelFile")MultipartFile file){
System.out.println("upload");
int num=0;
try {
Listlist=FileUtil.doUploadFile(file, request);
num=sListService.doUploadFile(list);
} catch (Exception e) {
e.printStackTrace();
System.out.println("导入失败");
return new ModelMap("info", "导入失败");
}
// model.addAttribute("info", ""+num+"条记录导入成功");
System.out.println(num+"条记录导入成功");
return new ModelMap("info", num+"条记录导入成功");
}
FileUtil工具类:
文件保存部分因为FileUtils报错而且不用就注掉了
该类调用工具类对Excel进行处理,获得处理结果List>,将处理结果进行处理,变为List
public static List doUploadFile(MultipartFile file, HttpServletRequest request) throws Exception {
// if (!file.isEmpty()) {
// try {
// // 这里将上传得到的文件保存指定目录下
// FileUtils.copyInputStreamToFile(file.getInputStream(),
// new File("d:\\upload\\file\\", System.currentTimeMillis() + file.getOriginalFilename()));
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
List list=new ArrayList();
InputStream in = null;
List> listob = null;
in = file.getInputStream();
listob = new ImportExcelUtil().getBankListByExcel(in, file.getOriginalFilename());
// 该处可调用service相应方法进行数据保存到数据库中,现只对数据输出
for (int i = 0; i < listob.size(); i++) {
List
Import
ExcelUtil工具类:
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
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;
public class ImportExcelUtil {
private final static String excel2003L = ".xls"; // 2003- 版本的excel
private final static String excel2007U = ".xlsx"; // 2007+ 版本的excel
/**
* 描述:获取IO流中的数据,组装成List>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public List> getBankListByExcel(InputStream in, String fileName) throws Exception {
}
/**
* 描述:根据文件后缀,自适应上传文件的版本
*
* @param inStr,fileName
* @return
* @throws Exception
*/
public Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
}
/**
* 描述:对表格中数值进行格式化
*
* @param cell
* @return
*/
public Object getCellValue(Cell cell) {
}
}
描述:获取IO流中的数据,组装成List>对象
getNumberOfSheets():sheet数目:1->n
getFirstRowNum、getLastRowNum:row位置:0-n
getFirstCellNum、getLastCellNum:Cell位置:0-n+1
/**
* 描述:获取IO流中的数据,组装成List>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public List> getBankListByExcel(InputStream in, String fileName) throws Exception {
List> list = null;
// 创建Excel工作薄
Workbook work = this.getWorkbook(in, fileName);
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null;
Row row = null;
Cell cell = null;
list = new ArrayList>();
// 遍历Excel中所有的sheet
for (int i = 0; i < work.getNumberOfSheets(); i++) {
sheet = work.getSheetAt(i);
if (sheet == null) {
continue;
}
// 遍历当前sheet中的所有行
for (int j = sheet.getFirstRowNum(); j < sheet.getLastRowNum() + 1; j++) {
row = sheet.getRow(j);
//getFirstRowNum/getFirstCellNum-->从0开始取
//去除第一行row.getFirstCellNum() == j == 0
if (row == null || row.getFirstCellNum() == j) {
continue;
}
// 遍历所有的列
List
描述:根据文件后缀,自适应上传文件的版本
读取Sheet,根据需求不同改变处理和返回值
/**
* 描述:根据文件后缀,自适应上传文件的版本
*
* @param inStr,fileName
* @return
* @throws Exception
*/
public Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
Workbook wb = null;
String fileType = fileName.substring(fileName.lastIndexOf("."));
if (excel2003L.equals(fileType)) {
wb = new HSSFWorkbook(inStr); // 2003-
} else if (excel2007U.equals(fileType)) {
wb = new XSSFWorkbook(inStr); // 2007+
} else {
throw new Exception("解析的文件格式有误!");
}
return wb;
}
描述:对表格中数值进行格式化:按需修改
原来没有if(cell==null),因为报错而加
/**
* 描述:对表格中数值进行格式化
*
* @param cell
* @return
*/
public Object getCellValue(Cell cell) {
Object value = null;
DecimalFormat df = new DecimalFormat("0"); // 格式化number String字符
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); // 日期格式化
DecimalFormat df2 = new DecimalFormat("0.00"); // 格式化数字
System.out.println("cell="+cell);
if(cell==null){
return "";
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if ("General".equals(cell.getCellStyle().getDataFormatString())) {
value = df.format(cell.getNumericCellValue());
} else if ("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) {
value = sdf.format(cell.getDateCellValue());
} else {
value = df2.format(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_BOOLEAN:
value = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK:
value = "";
break;
default:
break;
}
return value;
}
三、前台
使用Ajax+Form提交方式。此处前后台交互遇到问题,开始使用ModelAndView model.addAttribute,前台Ajax收不到data,
后来改用session.setAttribute方式,但是js中session为undefined无法使用,最后使用了ModelMap才可以,没有找到原因。
过滤:accept=".xlsx,application/vnd.ms-excel,application/vnd.openxmlformat-officedocument.spreadsheetml.sheet"
信息导入:
function
function uploadExcel(){
var excelFile=$("#excelFile").val();
if(excelFile==""||excelFile.length==0){
alert("请选择文件路径!(.xlsx)");
return;
}
if(excelFile.indexOf(".xlsx")==-1){
alert("请选择正确格式文件!(.xlsx)");
return;
}
var action = " ";
var option={
url: action,
type:"POST",
dataType : "json",
clearForm:true,
success:function(data){
console.log("data.info="+ data.info);
$.messager.alert('导入结果', data.info);
}
};
$("#uploadE").ajaxSubmit(option);
}