1. 程式人生 > >利用EXCEL檔案批量上傳使用者資訊

利用EXCEL檔案批量上傳使用者資訊

批量匯入使用者資訊

批量匯入通常是將指定格式的excel或word檔案上傳到伺服器,伺服器讀取上傳的檔案內容,將檔案內容全部讀取到資料庫的過程。
此案例包括:檔案下載、檔案上傳、EXCEL檔案解析、將解析後的資料存入資料庫。

操作步驟:

一、預備工作

0、引入包

檔案上傳:commons-fileupload-1.2.2.jar、commons-io-2.1.jar

檔案下載:不需要JAR包支援

XLS檔案解析:poi-3.7-20101029.jar

1、建表users

create table users(
id int primary key auto_increment,
name varchar
(20) not null, password varchar(32) not null, sex varchar(2) not null, birthday date not null, hobby varchar(50) not null, telephone varchar(15) not null, address varchar(50) not null, type int not null -- 1 admin 2 common user );

插入測試資料:

insert into users values(1,'admin','202CB962AC59075B964B07152D234B70'
,'男', '1980-1-1','體育,旅遊','13953311099','山東淄博',1);
insert into users values(2,'abc','202CB962AC59075B964B07152D234B70','女', '1990-1-1','體育,音樂','1895330000','山東濟南',2);

效果如下:

2、建立相應的JavaBean:

package cn.sdut.po;
public class User {
private int id;
private String name;
private String password;
private String sex;
private
String birthday; private String hobby; private String telephone; private String address; private int type; public User() { super(); } public User(int id, String name, String password, String sex, String birthday, String hobby, String telephone, String address, int type) { super(); this.id = id; this.name = name; this.password = password; this.sex = sex; this.birthday = birthday; this.hobby = hobby; this.telephone = telephone; this.address = address; this.type = type; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getType() { return type; } public void setType(int type) { this.type = type; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + ", sex=" + sex + ", birthday=" + birthday + ", hobby=" + hobby + ", telephone=" + telephone + ", address=" + address + ", type=" + type + "]"; } }

如果要進行批量匯入,需要給使用者提供一個模板供下載,user.xls(將其放置於WebRoot/excel/user.xls)

要在WebRoot下建立一個目錄 excel,存放excel模板user.xls.

檔案內容為:

序號 姓名 密碼 性別 出生年月 愛好 聯絡方式 地址    使用者型別(1-管理員 2-普通使用者)
1 李華 6666 1977-3-3 音樂;美術 196852452 北京朝陽 2

注意:資料型別與資料庫中的資料型別相匹配。需要特別注意資料的型別與日期型別的格式,見下圖。

二、檔案下載

0、準備工作:前端頁面——userMain.jsp,內容如下。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'userMain.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script src="js/calendar.js"></script>
<script>
function selectUser()
{
form1.action="<%=path%>/UserServlet?method=bycond";
form1.submit();
}
</script>
</head>
<body>
<center>
<h1>用 戶 管 理</h1></center>
<br>
<form action="" method="post" enctype="multipart/form-data" name="form1">
<p>查詢條件:
<input type="text" name="condition" id="condition">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出生日期:
<input name="datefrom" type="text" id="datefrom" size="10" onclick="new Calendar().show(this)">
~
<input name="dateto" type="text" id="dateto" size="10" onclick="new Calendar().show(this)">
&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" name="select" id="select" value=" 查 詢 " onclick="selectUser()">
</p>
<table width="899" border="1">
<tr>
<td width="67" align="center">選擇</td>
<td width="67" align="center">序號</td>
<td width="82" align="center">姓名</td>
<td width="70" align="center">性別</td>
<td width="99" align="center">出生日期</td>
<td width="88" align="center">愛好</td>
<td width="108" align="center">電話</td>
<td width="108" align="center">地址</td>
<td width="200" align="center">操作</td>
</tr>
<c:forEach items="${userList}" var="user" varStatus="status">
<tr>
<td align="center">
<input type="checkbox" name="id" id="id" value="${user.id}"></td>
<td align="center"> ${status.count} </td>
<td align="center">${user.name }</td>
<td align="center">${user.sex }</td>
<td align="center">${user.birthday }</td>
<td>${user.hobby }</td>
<td>${user.telephone }</td>
<td>${user.address}</td>
<td>&nbsp;
<a href="<%=path%>/UserServlet?method=del&id=${user.id}">刪除</a>
&nbsp; 修改&nbsp; 密碼復位</td>
</tr>
</c:forEach>
<tr>
<td height="47" colspan="9" align="center"><input type="submit" name="addUser" id="addUser" value=" 增加使用者 ">
&nbsp; &nbsp;
<input type="submit" name="batchDelete" id="batchDelete" value=" 批量刪除 ">
&nbsp; &nbsp;
<input name="batchResetPassword" type="submit" id="batchResetPassword" value="批量密碼復位">
&nbsp; &nbsp;</td>
</tr></table></form>
<tr>
<td height="47" colspan="9" align="left">
<form name="form2" method="post" action="<%=path%>/UserServlet?method=uploadExcel" enctype="multipart/form-data">
<p>
<h3>&nbsp;&nbsp;&nbsp;&nbsp; 匯入使用者
</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 選擇匯入檔案:
<input type="file" name="file" id="file">
<input type="submit" name="ok" id="ok" value="確定">
&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;
<a href="<%=path%>/UserServlet?method=downloadExcel&filename=user.xls"> <img src="<%=path%>/images/excel.png" alt="" width="30" height="30">&nbsp; 下載EXCEL樣例 </a>
</p>
<p>&nbsp;</p>
</form>
<p>&nbsp;</p>
<p><br><br>
</p></td>
</tr>
<p>&nbsp;</p>
${msg }
</body>
</html>

效果為:

1、下載流程

頁面中的下載相關程式碼:

<a href="<%=path%>/UserServlet?method=downloadExcel&filename=user.xls">
<img src="<%=path%>/images/excel.png" width="30" height="30">&nbsp; 下載EXCEL樣例
</a>

2、處理下載任務的Servlet

建立一個UserServlet,對映路徑為: /UserServlet

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String method=request.getParameter("method");//得到客戶端要進行何種操作
switch(method)
{
case "bycond":
queryUserByCondition(request,response);
break;
case "del":
delUser(request,response);
break;
case "downloadExcel":
downloadExcel(request,response);
break;
case "uploadExcel":
uploadExcel(request,response);
break;
}
}
private void downloadExcel(HttpServletRequest request,
HttpServletResponse response) throws IOException {
//從客戶端得到待寫出檔案的名稱
String filename=request.getParameter("filename");
//確定待寫出的檔案位置
String path=getServletContext().getRealPath("/excel");
//瀏覽器層面的處理
response.setHeader("Content-disposition","attachment;filename="+filename);
//實際寫出檔案
//建立輸入流
File file=new File(path,filename);
System.out.println(file);
InputStream is=new FileInputStream(file);
//得到輸出流
ServletOutputStream writer = response.getOutputStream();
//邊讀邊寫
byte[] bytes=new byte[1024];
int len=0;
while((len=(is.read(bytes)))!=0)
{
writer.write(bytes, 0, len);
}
//寫出資料後做好掃尾工作,清空緩衝區,關閉輸入輸出流
writer.flush();
is.close();
writer.close();
}

執行,檔案可以下載。

下載後,開啟檔案內容為:

在裡在填充上資料,以便於進行檔案的上傳。
說明:模板資料暫時沒有刪除,如果需要的話可刪除掉,填入真實有效的資料。

三、檔案上傳及批量匯入流程

主要步驟:

1、上傳excel檔案到伺服器

2、 伺服器端解析excel檔案並存儲到連結串列集合中

3、 呼叫DBUtils的batch方法進行批量處理

實施步驟:

1. 頁面上傳 JSP檔案程式碼:

<form name="form2"
method="post"
action="<%=path%>/UserServlet?method=uploadExcel"
enctype="multipart/form-data">
<p>
<h3>&nbsp;&nbsp;&nbsp;&nbsp; 匯入使用者
</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 選擇匯入檔案:
<input type="file" name="file" id="file">
<input type="submit" name="ok" id="ok" value="確定"> &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;
<a href="<%=path%>/UserServlet?method=downloadExcel&filename=user.xls"> <img src="<%=path%>/images/excel.png" alt="" width="30" height="30">&nbsp; 下載EXCEL樣例 </a>
</p>
<p>&nbsp;</p>
</form>

2. BaseDao中批量操作方法

//批量操作資料庫的方法
public boolean bactchUpdate(String sql,Object[][] param)
{
int[] result=new int[param.length];
int r=1;
Connection conn=getConn(); //得到連線
QueryRunner runner=new QueryRunner(); //得到執行物件
try {
result=runner.batch(conn,sql,param);// 批量進行資料庫操作
} catch (SQLException e) {
e.printStackTrace();
}
finally
{
DbUtils.closeQuietly(conn); //關閉資料庫連線
}
//對返回資料進行加工,將整型陣列轉化為布林型別
for(int i=0;i<result.length;i++)
{
r*=result[i];
}
return r>0?true:false;
}

3、建立UserDao,繼承BaseDao類,定義批量插入資料的方法

public class UserDao extends BaseDao{
//批量匯入使用者
public boolean batchImport(List<User> users)
{
boolean flag=false;
String sql="insert into users(name,password,sex,birthday, hobby,telephone,address,type) values(?,?,?,?,?,?,?,?)";
Object[][] params=new Object[users.size()][8];
for(int i=0;i<users.size();i++)
{
User user = users.get(i);
params[i][0]=user.getName();
params[i][1]=user.getPassword();
params[i][2]=user.getSex();
params[i][3]=user.getBirthday();
params[i][4]=user.getHobby();
params[i][5]=user.getTelephone();
params[i][6]=user.getAddress();
params[i][7]=user.getType();
}
flag = bactchUpdate(sql, params);
return flag;
}
}

4.編寫UserServlet實現批量請求

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String method=request.getParameter("method");//得到客戶端要進行何種操作
switch(method)
{
case "bycond":
queryUserByCondition(request,response);
break;
case "del":
delUser(request,response);
break;
case "downloadExcel":
downloadExcel(request,response);
break;
case "uploadExcel":
uploadExcel(request,response);
break;
}
}
private void uploadExcel(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserDao dao=new UserDao();
//第一步,檔案上傳,需要commons-fileupload-1.2.2.jar和commons-io-2.1.jar的支援
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
boolean isuploadSuccess = false;
File excelFile = null;
try {
// 設定上傳路徑
String uploaddir = request.getSession().getServletContext().getRealPath("/excels");
File upFile = new File(uploaddir);
if (!upFile.exists()) {
upFile.mkdirs();
}
if (isMultipart == true) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items;
items = upload.parseRequest(request);
Iterator<FileItem> itr = items.iterator();
while (itr.hasNext()) {
// 單檔案上傳
FileItem item = (FileItem) itr.next();
if (!item.isFormField()) { // 檔案,不包含普通表單內容
File uploadFile = new File(item.getName());
excelFile = new File(uploaddir, uploadFile.getName());
try {
item.write(excelFile);
isuploadSuccess = true;
} catch (Exception e) {
e.printStackTrace();
isuploadSuccess = false;
System.out.println("上傳失敗!!");
}
} else {
// 普通表單內容 不處理
System.out.println(item.toString());
}
}
//第二步,解析檔案內容(需要poi-3.7-20101029.jar的支援),將資料封裝到List中
// 如果檔案上傳成功,解析excel,存入List集合中
//如果excel資料比較大,List可能放不下的問題
//你可以分頁讀取excel,一個List裡面放2W條資料應該沒什麼問題
// 根據excel的格式 解析自己的資料,此處使用者資訊包含如下欄位:
//1序號、2姓名、3密碼、4性別、5出生年月、6愛好、7聯絡方式、8地址、9使用者型別(1-管理員 2-普通使用者)
List<User> list = new ArrayList<User>();
if (isuploadSuccess) { //若上傳成功,就解析其中的資料
// poi解析
FileInputStream fis = null;
try {
System.out.println(excelFile.getAbsolutePath());
fis = new FileInputStream(excelFile);
HSSFWorkbook book = new HSSFWorkbook(fis);//由檔案輸入流得到工作簿物件
HSSFSheet sheet = book.getSheetAt(0); // 得到工作簿的第一個sheet
int lastRowNum = sheet.getLastRowNum(); // 得到有資料的最大行數
System.out.println("行數:" + lastRowNum);
// 一般excel第一行是標題
HSSFRow row = null;
for (int i = 1; i <= lastRowNum; i++) {
row = sheet.getRow(i); //得到工作表的第 i行
String name = getCellValue(row, 1);
String password = getCellValue(row, 2);
String sex = getCellValue(row, 3);
String birthday = getCellValue(row, 4);
String hobby = getCellValue(row, 5);
String telephone = getCellValue(row, 6);
String address = getCellValue(row, 7);
int type = getIntCellValue(row, 8);
if(name.length()*password.length()*sex.length()*
birthday.length()*hobby.length()*telephone.length()
*address.length()*type!=0)
{
User user = new User(0,name,password,sex,birthday,hobby,telephone,address,type);
list.add(user);
}
}
} catch (Exception e) {
System.out.println("excel解析出錯!!!");
e.printStackTrace();
}
} else {
System.out.println("失敗:");
}
// 解析excel成功,批量新增資料
System.out.println(list);
boolean result = dao.batchImport(list);
if(result == true){
response.getWriter().print("匯入成功!<br>");
}else{
response.getWriter().print("匯入失敗!<br>");
}
} else {
System.out.print("the enctype must be multipart/form-data");
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
request.getRequestDispatcher("/UserServlet?method=bycond").forward(request, response); //重新顯示資料
}
//得到row行cellIndex列的字串資料
private String getCellValue(HSSFRow row, int cellIndex) {
String cellValue = "";
cellValue = row.getCell(cellIndex).getStringCellValue();
return cellValue;
}
//得到row行cellIndex列的int型別資料
private int getIntCellValue(HSSFRow row, int cellIndex) {
int cellValue = 0;
cellValue = (int) row.getCell(cellIndex).getNumericCellValue();
return cellValue;
}
//得到row行cellIndex列的long型別資料
private long getLongCellValue(HSSFRow row, int cellIndex) {
long cellValue = 0;
cellValue = (long) row.getCell(cellIndex).getNumericCellValue();
return cellValue;
}

執行檔案上傳後的效果為: