您的位置:首页 > 运维架构 > Apache

使用Apache FileUpload 上传以及 JExcelApi 生成Excel文件

2008-09-29 18:14 495 查看
欢迎点击此处订阅本Blog





本文转载自:[b]http://www.blogjava.net/rosen

[/b]

最近遇到点读取 Excel 数据的问题,于是花了点时间找开源工具。
要解析 Excel,首当其冲的是上传文件,以前在项目里我们用 SmartUpload 进行上传,不过这个项目似乎已经停止开发了,于是在这里我使用 Apache Commons FileUpload,可以在 http://jakarta.apache.org/commons/fileupload 找到。目前该项目的最新版本是 1.1.1,网上有大量的范例程序,不过后来用的时候发现大部分方法在新版本中都不推荐使用了,于是好好读了一回 API 和官方范例。

先来看看如何上传文件,Servlet 很简单,在这里我限制了最大上传量为 1M,且直接读进内存中,不进行磁盘临时文件缓存。


import
java.io.IOException;

import
java.io.PrintWriter;

import
java.io.File;

import
java.net.URI;

import
java.net.URL;

import
javax.servlet.ServletException;

import
javax.servlet.http.HttpServlet;

import
javax.servlet.http.HttpServletRequest;

import
javax.servlet.http.HttpServletResponse;

import
java.util.List;

import
org.apache.commons.fileupload.RequestContext;

import
org.apache.commons.fileupload.servlet.ServletRequestContext;

import
org.apache.commons.fileupload.servlet.ServletFileUpload;

import
org.apache.commons.fileupload.disk.DiskFileItemFactory;

import
org.apache.commons.fileupload.FileItem;

public

class
UploadServlet
extends
HttpServlet {


/**


* Constructor of the object.

*/



public
UploadServlet() {

super
();
}


/**


* Destruction of the servlet.

*/



public

void
destroy() {

super
.destroy();
}


public

void
doGet(HttpServletRequest request, HttpServletResponse response)

throws
ServletException, IOException {
}


/**


* 上传文件
*
*
@param
request
*
@param
response
*
@throws
ServletException
*
@throws
IOException

*/



public

void
doPost(HttpServletRequest request, HttpServletResponse response)

throws
ServletException, IOException {
response.setContentType(
"
text/html
"
);
response.setCharacterEncoding(
"
gbk
"
);
PrintWriter out
=
response.getWriter();
out.println(
"
<html>
"
);
out.println(
"
<head><title>提示</title></head>
"
);
out.println(
"
<body>
"
);

//
不用获取 URL 对象也行,直接用 getServletContext().getRealPath("/") 代替。




URL url
=
getServletContext().getResource(
"
/
"
);

//
从 HTTP servlet 获取 fileupload 组件需要的内容




RequestContext requestContext
=

new
ServletRequestContext(request);

//
判断是否包含 multipart 内容





if
(ServletFileUpload.isMultipartContent(requestContext)) {

//
创建基于磁盘的文件工厂




DiskFileItemFactory factory
=

new
DiskFileItemFactory();

//
设置直接存储文件的极限大小,一旦超过则写入临时文件以节约内存。默认为 1024 字节




factory.setSizeThreshold(
1024

*

1024
);

//
创建上传处理器,可以处理从单个 HTML 上传的多个上传文件。




ServletFileUpload upload
=

new
ServletFileUpload(factory);

//
最大允许上传的文件大小




upload.setSizeMax(
1024

*

1024
);

//
处理上传




List items
=

null
;

try
{
items
=
upload.parseRequest(requestContext);

//
由于提交了表单字段信息,需要进行循环区分。





for
(
int
i
=

0
; i
<
items.size(); i
++
) {
FileItem fi
=
(FileItem) items.get(i);

//
如果不是表单内容,取出 multipart。





if
(
!
fi.isFormField()) {

//
上传文件路径和文件、扩展名。




String sourcePath
=
fi.getName();
String[] sourcePaths
=
sourcePath.split(
"
////
"
);

//
获取真实文件名




String fileName
=
sourcePaths[sourcePaths.length
-

1
];

//
创建一个待写文件




File uploadedFile
=

new
File(
new
URI(url.toString()
+
fileName));

//
写入




fi.write(uploadedFile);
out.println(fileName
+
"
上传成功。
"
);
}
}
}
catch
(Exception e) {
out.println(
"
上传失败,请检查上传文件大小是否超过1兆,并保证在上传时该文件没有被其他程序占用。
"
);
out.println(
"
<br>原因:
"
+
e.toString());
e.printStackTrace();
}
}
out.println(
"
</body>
"
);
out.println(
"
</html>
"
);
out.flush();
out.close();
}


/**


* Initialization of the servlet.
*
*
@throws
ServletException

*/



public

void
init()
throws
ServletException {
}
}



上面的程序示范了如何上传文件到服务器,本文的主要目的不光是上传,还要进行 Excel 解析,抽取有用的内容。开源的 Excel 解析器很多,在此我选择了 JExcelApi,可以在 http://jexcelapi.sourceforge.net 找到,据说是韩国人开发的,最新版本是 2.6.2。为什么没有选 POI,原因也是因为它 N 久没有更新了。我总是喜欢最新的东东,比如 Adobe 的 PDF Reader,硬是下载了 8.0,结果感觉还没有 6.0 好用。:(

以下程序修改直上传,做了部分调整,取消了文件储存,直接通过读取输入流进行解析,并假设约定的 Excel 文件有五列 N 行,第一行为标题信息。


import
java.io.IOException;

import
java.io.PrintWriter;

import
javax.servlet.ServletException;

import
javax.servlet.http.HttpServlet;

import
javax.servlet.http.HttpServletRequest;

import
javax.servlet.http.HttpServletResponse;

import
java.util.List;

import
org.apache.commons.fileupload.RequestContext;

import
org.apache.commons.fileupload.servlet.ServletRequestContext;

import
org.apache.commons.fileupload.servlet.ServletFileUpload;

import
org.apache.commons.fileupload.disk.DiskFileItemFactory;

import
org.apache.commons.fileupload.FileItem;

import
jxl.Workbook;

import
jxl.Sheet;

import
jxl.Cell;

public

class
UploadServlet
extends
HttpServlet {


/**


* Constructor of the object.

*/



public
UploadServlet() {

super
();
}


/**


* Destruction of the servlet.

*/



public

void
destroy() {

super
.destroy();
}


public

void
doGet(HttpServletRequest request, HttpServletResponse response)

throws
ServletException, IOException {
}


/**


* 上传文件
*
*
@param
request
*
@param
response
*
@throws
ServletException
*
@throws
IOException

*/



public

void
doPost(HttpServletRequest request, HttpServletResponse response)

throws
ServletException, IOException {
response.setContentType(
"
text/html
"
);
response.setCharacterEncoding(
"
gbk
"
);
PrintWriter out
=
response.getWriter();
out.println(
"
<html>
"
);
out.println(
"
<head><title>提示</title></head>
"
);
out.println(
"
<body>
"
);

//
声明文件域




FileItem fileItem
=

null
;

//
从 HTTP servlet 获取 fileupload 组件需要的内容




RequestContext requestContext
=

new
ServletRequestContext(request);

//
判断是否包含 multipart 内容,如果不包含,则不进行任何处理。





if
(ServletFileUpload.isMultipartContent(requestContext)) {

//
创建基于磁盘的文件工厂




DiskFileItemFactory factory
=

new
DiskFileItemFactory();

//
设置直接存储文件的极限大小,一旦超过则写入临时文件以节约内存。默认为 1024 字节




factory.setSizeThreshold(
1024

*

1024
);

//
创建上传处理器,可以处理从单个 HTML 上传的多个上传文件。




ServletFileUpload upload
=

new
ServletFileUpload(factory);

//
最大允许上传的文件大小




upload.setSizeMax(
1024

*

1024
);

try
{

//
处理上传




List items
=

null
;
items
=
upload.parseRequest(requestContext);

//
由于提交了表单字段信息,需要进行循环区分。





for
(
int
i
=

0
; i
<
items.size(); i
++
) {
FileItem fi
=
(FileItem) items.get(i);

//
如果不是表单内容,取出 multipart。





if
(
!
fi.isFormField()) {
fileItem
=
fi;

//
一次只上传单个文件





break
;
}
}
out.println(parseExcel(fileItem));
}
catch
(Exception e) {
out.println(
"
上传失败!请检查上传的文件是否为excel格式、信息是否完整完整、且大小是否超过1兆。
"
);
out.println(
"
<br>原因:
"
+
e.toString());
e.printStackTrace();
}
}
out.println(
"
</body>
"
);
out.println(
"
</html>
"
);
out.flush();
out.close();
}


/**


* 分析excel文件
*
*
@param
FileItem fi 文件域
*
@return
String
*
@throws
Exception

*/



private
String parseExcel(FileItem fi)
throws
Exception{

//
声明 Workbook




Workbook workbook
=

null
;

try
{
workbook
=
Workbook.getWorkbook(fi.getInputStream());
Sheet sheet
=
workbook.getSheet(
0
);

//
总行数





int
count
=
sheet.getRows();

//
取出标题




String a1
=
sheet.getCell(
0
,
0
).getContents();
String a2
=
sheet.getCell(
1
,
0
).getContents();
String a3
=
sheet.getCell(
2
,
0
).getContents();
String a4
=
sheet.getCell(
3
,
0
).getContents();
String a5
=
sheet.getCell(
4
,
0
).getContents();

//
取出内容





for
(
int
i
=

1
;i
<
count;i
++
){
Cell[] cells
=
sheet.getRow(i);
System.out.println(cells[
0
].getContents()

+
cells[
1
].getContents()
+
cells[
2
].getContents()

+
cells[
3
].getContents()
+
cells[
4
].getContents());
}

return

"
上传成功。
"
;
}
catch
(Exception e){

throw
e;
}
finally
{

if
(workbook
!=
null
){
workbook.close();
}
}
}


/**


* Initialization of the servlet.
*
*
@throws
ServletException

*/



public

void
init()
throws
ServletException {
}
}


JExcelApi 用起来很简单,而且还可以根据 Excel 中数据类型转换成 Java 数据类型,比如 int、double,具体信息可以参考它的开发指南。当然,本范例还提供现构造 Excel 然后下载的方法,如果以后遇到,一定继续完善。

------------------------------------------------------------------------------------------------
关于生成 excel 和下载,一月份的文章还留了个尾巴,今天把它补充上去。2007-04-22 by rosen jiang

代码如下,放在 servlet 中,io 异常我没捕获,直接由 get or post 方法抛出,当然,如果更严谨点可以放在 finally 里关闭。
//设置输出格式和头信息
response.setContentType("application/x-msdownload;charset=GBK");
String filename = new String("供应商报价清单.xls".getBytes("GBK"),"ISO_8859_1");
response.setHeader("Content-Disposition","attachment;filename="+filename);

//虚拟数据
String materialName = "马桶"; //材料名
String size = "200×300"; //规格
String unit = "台"; //单位
String qty = "2"; //数量
String band = "不知道牌子"; //材料品牌
String company = "成都某厂"; //厂家名
String memo = "质量可靠"; //备注
String price = "20.30"; //价格
String repDate = "2007-04-11"; //报价时间
List<String[]> list = new ArrayList<String[]>();
for(int i = 10; i > 0; i--){
String[] outPut = {materialName,size,unit,qty+i,band,company,memo,price,repDate};
list.add(outPut);
}

//输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//构造工作区
WritableWorkbook workbook = Workbook.createWorkbook(baos);
//构造 sheet
WritableSheet sheet = workbook.createSheet("报价清单", 0);
//构造粗标题字体
WritableFont blodFont = new WritableFont(WritableFont.TAHOMA,10,WritableFont.BOLD, false);
WritableCellFormat blodFormat = new WritableCellFormat (blodFont);
Label label = null;
try {
//标题行
label = new Label(0, 0, "材料名", blodFormat);
sheet.addCell(label);
label = new Label(1, 0, "规格", blodFormat);
sheet.addCell(label);
label = new Label(2, 0, "单位", blodFormat);
sheet.addCell(label);
label = new Label(3, 0, "数量", blodFormat);
sheet.addCell(label);
label = new Label(4, 0, "材料品牌", blodFormat);
sheet.addCell(label);
label = new Label(5, 0, "厂家名", blodFormat);
sheet.addCell(label);
label = new Label(6, 0, "备注", blodFormat);
sheet.addCell(label);
label = new Label(7, 0, "价格", blodFormat);
sheet.addCell(label);
label = new Label(8, 0, "报价时间", blodFormat);
sheet.addCell(label);
//输出业务数据
for(int i = 1; i <= list.size(); i++){
String[] outPut = list.get(i-1);
label = new Label(0, i, outPut[0]);
sheet.addCell(label);
label = new Label(1, i, outPut[1]);
sheet.addCell(label);
label = new Label(2, i, outPut[2]);
sheet.addCell(label);
label = new Label(3, i, outPut[3]);
sheet.addCell(label);
label = new Label(4, i, outPut[4]);
sheet.addCell(label);
label = new Label(5, i, outPut[5]);
sheet.addCell(label);
label = new Label(6, i, outPut[6]);
sheet.addCell(label);
label = new Label(7, i, outPut[7]);
sheet.addCell(label);
label = new Label(8, i, repDate);
sheet.addCell(label);
}
//写入文件
workbook.write();
workbook.close();

//向浏览器返回文件流
OutputStream os = response.getOutputStream();
os.write(baos.toByteArray());
os.flush();
os.close();
baos.close();
} catch (RowsExceededException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
}

生成 excel 的样子是这样的:



请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处:http://www.blogjava.net/rosen
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: