项目背景:从一个系统中导出数据,导入的另一个系统中,导出的数据以.zip形式,里面的内容包括,一个文件夹:文件夹中是要上传文档信息对应的附件文件;两个.xls:一个是上传的文档信息,对应文档表,另一个是每个文档信息对应的附件信息,对应的是附件表。两个excel存在一个Map<String,List<?>>中,文档信息map的key为wdxx,对应的value为List<Wdgl>;附件信息的key为wdfjxx,对应的value值为List<Fjxx>。
前台:
<form id="importForm" method="post" enctype="multipart/form-data"> 上传文件时的设置值
<table class="table-form">
<tr>
<td class="td-title col4" ><label>导入文件<span class="fred">*</span></label></td>
<td colspan="3" id="fjxxfile" >
<span id="fjxxsjfjcon">
<input type="file" class="myfile easyui-validatebox" id="wdxx" name="uploadFile"/>
</span>
</td>
</tr>
</table>
</form>
后台: 在文件的action中定义
单文件
private File uploadFile; // 实际上传的单个文件
private String uploadFileContentType; // 上传单个文件的类型
private String uploadFileFileName; // 上传单个文件的名称
多文件
private File[] uploadFiles; // 上传的多个文件
private String[] uploadFilesContentType; // 上传多个文件的类型
private String[] uploadFilesFileName; // 上传多个文件的名称
给出相应的get、set方法
导入的方法
public void importW(){
String fileName = this.getUploadFileFileName();
UUID uuid = UUID.randomUUID();
if(StringUtils.isNotBlank(fileName)){
//上传文件到服务器端,创建文件夹并加密文件名
this.uploadFile("test/"+uuid);
//获得上传的到服务器的文件(已经加密)
String prefix = fileName.substring(0,fileName.lastIndexOf("."));
String suffix = fileName.substring(fileName.lastIndexOf("."));
String newFileName = MD5Util.md5(prefix);
File newFile = new File(newFileName+suffix);
//获取当前计算机的根目录,同时创建test_fileUpload文件夹
String absolute = getRootPath();
String path = "test/"+uuid;
File f = new File(absolute+path+"/"+newFileName+suffix);
//解压zip
try {
//读取zip包
Map<String,List<?>> resultMap = readFromZip(f,new ImportFormatter("yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void uploadFile(String dir){
String absolutePath = getRootPath();
//自定义一个目录
String path = absolutePath + dir;
File file = new File(path);
if(!file.exists()){
file.mkdir();
}
try {
if(this.getTest().length()>0){
String fileName = getTestFileName();
String prefix = fileName.substring(0,fileName.lastIndexOf("."));
String suffix = fileName.substring(fileName.lastIndexOf("."));
/*对文件名进行md5加密,md5(Messager-Digest Algorithm 信息-摘要 算法
1.运用一种安全的散列算法;
2.其过程是不可逆的,即根据输出值不能得到原始的明文,除非用穷举法进行一一对比
),直接调用的公司封装的方法*/
String newFileName = MD5Util.md5(prefix);
File newFile = new File(path,newFileName+suffix);
FileUtils.copyFile(getTest(), newFile);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取当前计算机的根目录,同时创建test_fileUpload文件夹
public String getRootPath(){
//获取用户目录 java获得系统的参数用System.getProperties()方法
String userPath = System.getProperties().getProperty("user.home");
String dirPath = "/test_fileUpload";
String rootPath = userPath + dirPath;
File file = new File(rootPath);
//test_fileUpload文件夹不存在则创建test_fileUpload文件夹
if(!file.exists()){
file.mkdirs();
}
return rootPath + "/";
}
//md5加密,不过不明白
public static String md5(String str) {
return bytes2Hex(md5(str.getBytes()));
}
//读取zip包
public Map<String,List<?>> readFromZip(File file,ImportFormatter formatter) throws Exception{
Map<String,List<?>> resultMap = new HashMap<String,List<?>>();
//解压文件到临时路径 test_fileUpload/unZipTemp/xxxxx/
String tempPath = getRootPath()+"/unZipTemp/"+new Date().getTime();
//上传文件的路径
File upLoadPath = new File(getRootPath());
if(file != null && file.exists()){
//解压文件到临时路径test_fileUpload/unZipTemp/xxx/
unZip(file.getAbsolutePath(),tempPath);
//获取解压的文件夹test_fileUpload/unZipTemp/xxxxx
File unzip = new File(tempPath);
//获取解压的文件夹里的上传文件test_fileUpload/unZipTemp/xxx/xxx
String basePath = unzip.listFiles()[0].getAbsolutePath();
//处理Excel信息
File unZipFile = new File(basePath);
File[] fileList = unZipFile.listFiles();
for(File tempFile : fileList){
if(tempFile.exists()){
//处理附件信息
if(tempFile.isDirectory()){
FileUtils.copyDirectory(tempFile, upLoadPath);
}else{
//处理Excel
String fileName = tempFile.getName();
String prefix = fileName.substring(0,fileName.lastIndexOf("."));
//获得excel中的数据
List<?> list = readValue(tempFile,prefix,formatter);
resultMap.put(prefix, list);
}
}
}
//删除临时文件夹的内容
FileUtils.deleteDirectory(unzip);
}
return resultMap;
}
//解压压缩包
public void unZip(String sourcePath,String targetPath) throws IOException{
//创建一个ZipFile实体类,第一个参数为压缩文件的绝对路径,第二个参数为编码方式,设置为GBK目的是使其支持中文
ZipFile zf = new ZipFile(sourcePath,"GBK");
//利用了Enumeration类,获得的zipEntry是无序的
@SuppressWarnings("rawtypes")
Enumeration e = zf.getEntries();
//判断枚举类是否还有更多的元素
while(e.hasMoreElements()){
//如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素
ZipEntry ze = (ZipEntry)e.nextElement();
String zipName = ze.getName();
String path = targetPath +"/"+ zipName;
//判断该元素是否为文件夹
if(ze.isDirectory()){
File dirFile = new File(path);
if(!dirFile.exists()){
//dirFile.mkdir();只能在已经存在的目录中创建文件夹
dirFile.mkdirs(); //可以在不存的目录中创建文件夹
}
}else{
File fileDirFile = new File(path.substring(0,path.lastIndexOf("/")));
if(!fileDirFile.exists()){
fileDirFile.mkdirs();
}
//BufferedOutputStream是一个带有缓冲区域的OutputStream
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
/*BufferedInputStream是一个带有缓冲区域的InputStream,
当read时会先把缓冲区填满,然后下次读取是直接从缓冲区读取。
当读取的位置大于缓冲区时会再一次加载缓冲区。*/
BufferedInputStream bis = new BufferedInputStream(zf.getInputStream(ze));
//设置缓冲区的大小
byte[] readContent = new byte[1024];
//这个缓冲区数组的作用在于对源进行数据块访问,而不是一字节一字节的访问,也就是进行一次I/O将一块数据存到缓冲区中,
//再从缓冲区中read,当缓冲区为空时再重新读新的数据块
//read方法返回当前位置的后一位置byte值(int表示)
int readCount = bis.read(readContent);
while(readCount != -1){
//使用write方法写入时,实际上先将数据写入到缓冲区
bos.write(readContent,0,readCount);
readCount = bis.read(readContent);
}
bos.close();
}
}
zf.close();
}
//读取Excel获得实体列表
public List<?> readValue(File file,String prefix,ImportFormatter formatter) throws Exception{
List<Object> list = new ArrayList<Object>();
String classUrl = PropertyGetter.getString(prefix + ".classURL");
String fieldStr = PropertyGetter.getString(prefix + ".fields");
String xy = PropertyGetter.getString(prefix + ".xy");
String typeStr = PropertyGetter.getString(prefix + ".types");
String[] fields = fieldStr.split(",");
String[] types = typeStr.split(",");
int startRow = Integer.parseInt(xy.substring(0,xy.lastIndexOf(",")));
int startClumn = Integer.parseInt(xy.substring(xy.lastIndexOf(",")+1));
InputStream is = new FileInputStream(file);
//org.apache.poi.hssf.usermodel.HSSFWorkbook 声明一个工作薄
HSSFWorkbook hssfWorkBook = new HSSFWorkbook(is);
//循环工作表
for(int numSheet=0;numSheet<hssfWorkBook.getNumberOfSheets();numSheet++){
HSSFSheet hssfSheet = hssfWorkBook.getSheetAt(numSheet);
if(hssfSheet == null){
continue;
}
//循环Row
for(int rowNum=startRow;rowNum<=hssfSheet.getLastRowNum();rowNum++){
HSSFRow hssfRow = hssfSheet.getRow(rowNum);
if(hssfRow == null){
continue;
}
//一下两句代码相当于Object object = new Object();
/*用到了反射机制*/
Class classLoader = Class.forName(classUrl);
Object object = classLoader.newInstance();
//循环Cell
for(int i=0;i<fields.length;i++){
//将属性的首字母变为大写
String firstUpper = fields[i].substring(0,1).toUpperCase()+fields[i].substring(1);
Method method = classLoader.getMethod("set"+firstUpper, Class.forName(types[i]));
HSSFCell column = hssfRow.getCell(i+startClumn);
if(column == null){
continue;
}
//判断值的类型后,进行强制类型转换
if(types[i].equals("java.lang.String")){
method.invoke(object, getValue(column));
}else if(types[i].equals("java.lang.Integer")){
method.invoke(object, getValue(column));
}else if(types[i].equals("java.util.Date")){
if(formatter == null){
formatter = new ImportFormatter("yyyy-MM-dd");
}
method.invoke(object, DateUtils.getDate(getValue(column, formatter),formatter.getDateFormat()));
}else if(types[i].equals("java.math.BigDecimal")){
method.invoke(object, new BigDecimal(getValue(column)));
}else if(types[i].equals("java.lang.Double")){
method.invoke(object, Double.parseDouble(getValue(column)));
}else if(types[i].equals("java.lang.Float")){
method.invoke(object, Float.parseFloat(getValue(column)));
}else if(types[i].equals("java.lang.Short")){
String value = getValue(column);
if(StringUtils.isNotBlank(value)){
value = value.contains(".")?value.substring(0,value.lastIndexOf(".")):value;
method.invoke(object, value);
}
}else{
method.invoke(object, new Object[]{});
}
}
list.add(object);
}
}
return list;s
}
/*
* 方法描述 : 得到Excel表中的值
* 参数: excel中的每一个格子
* 返回值:excel中每一个格子中的值
*/
@SuppressWarnings("static-access")
public String getValue(HSSFCell hssfCell){
int num = hssfCell.getCellType();
if(num == hssfCell.CELL_TYPE_BOOLEAN){
//返回布尔类型的值
return String.valueOf(hssfCell.getBooleanCellValue());
}else if(num == hssfCell.CELL_TYPE_NUMERIC){
if(HSSFDateUtil.isCellDateFormatted(hssfCell)){
Date date = HSSFDateUtil.getJavaDate(hssfCell.getNumericCellValue());
//调用公司的方法,就是将日期格式化
return DateUtils.dateToDateString(date, "yyyy-MM-dd HH:mm:ss");
}
//返回数值类型的值
return String.valueOf(hssfCell.getNumericCellValue());
}else{
//返回字符串类型的值
return String.valueOf(hssfCell.getStringCellValue());
}
}
/**
* 实体类中字段为Date时格式化得到Excel表中的值
* @param hssfCell Excel中的每一个格子
* @param formatter 格式化参数
* @return Excel中每一个格子中的值
*/
@SuppressWarnings("static-access")
private static String getValue(HSSFCell hssfCell, ImportFormatter formatter) {
if (hssfCell.getCellType() == hssfCell.CELL_TYPE_BOOLEAN) {
// 返回布尔类型的值
return String.valueOf(hssfCell.getBooleanCellValue());
} else if (hssfCell.getCellType() == hssfCell.CELL_TYPE_NUMERIC) {
if(HSSFDateUtil.isCellDateFormatted(hssfCell)) {
Date dt = HSSFDateUtil.getJavaDate(hssfCell.getNumericCellValue());
return DateUtils.dateToDateString(dt,"yyyy-MM-dd HH:mm:ss");
}
return String.valueOf(hssfCell.getNumericCellValue());
} else {
// 返回字符串类型的值
String format = formatter.getDateFormat(); //自己传入的日期格式
String cellValue = hssfCell.getStringCellValue(); //excel中的值
String replaceChar = ""; //需要替换的字符;
if (!StringUtils.isBlank(format)) {
if (format.contains("/")) {
replaceChar = "/";
} else if (format.contains("-")){
replaceChar = "-";
}
}
if (!StringUtils.isBlank(cellValue)) {
if (cellValue.contains("-")) {
cellValue = cellValue.replace("-", replaceChar);
} else if (cellValue.contains("/")) {
cellValue = cellValue.replace("/", replaceChar);
} else {
if (cellValue.length() < 8) {
throw new RuntimeException("格式错误");
} else {
cellValue = cellValue.substring(0, 4) + replaceChar + cellValue.substring(4, 6) + replaceChar + cellValue.substring(6);
}
}
}
return String.valueOf(cellValue);
}
}