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

<!-- Feedsky FEED发布代码开始 --> 欢迎点击此处订阅本Blog <!-- FEED自动发现标记开始 --> <link title="RSS 2.0" type="application/rss+xml" href="http://feed.feedsky.com/softwave" rel="alternate"> <!-- FEED自动发现标记结束 --> Blog 订阅

<!--Google 468*60横幅广告开始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as"; google_ad_type = "image"; //2007-07-26: CSDN google_ad_channel = "6063905817"; google_color_border = "6699CC"; google_color_bg = "E6E6E6"; google_color_link = "FFFFFF"; google_color_text = "333333"; google_color_url = "AECCEB"; google_ui_features = "rc:6"; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--Google 468*60横幅广告结束-->

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

最近遇到点读取 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{

/**
*Constructoroftheobject.
*/
public UploadServlet(){
super ();
}

/**
*Destructionoftheservlet.
*/
public void destroy(){
super .destroy();
}

public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
}

/**
*上传文件
*
*
@param request
*
@param response
*
@throws ServletException
*
@throws IOException
*/
public void doPost(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
response.setContentType(
" text/html " );
response.setCharacterEncoding(
" gbk " );
PrintWriterout
= response.getWriter();
out.println(
" <html> " );
out.println(
" <head><title>提示</title></head> " );
out.println(
" <body> " );
// 不用获取URL对象也行,直接用getServletContext().getRealPath("/")代替。
URLurl = getServletContext().getResource( " / " );
// 从HTTPservlet获取fileupload组件需要的内容
RequestContextrequestContext = new ServletRequestContext(request);
// 判断是否包含multipart内容
if (ServletFileUpload.isMultipartContent(requestContext)){
// 创建基于磁盘的文件工厂
DiskFileItemFactoryfactory = new DiskFileItemFactory();
// 设置直接存储文件的极限大小,一旦超过则写入临时文件以节约内存。默认为1024字节
factory.setSizeThreshold( 1024 * 1024 );
// 创建上传处理器,可以处理从单个HTML上传的多个上传文件。
ServletFileUploadupload = new ServletFileUpload(factory);
// 最大允许上传的文件大小
upload.setSizeMax( 1024 * 1024 );
// 处理上传
Listitems = null ;
try {
items
= upload.parseRequest(requestContext);
// 由于提交了表单字段信息,需要进行循环区分。
for ( int i = 0 ;i < items.size();i ++ ){
FileItemfi
= (FileItem)items.get(i);
// 如果不是表单内容,取出multipart。
if ( ! fi.isFormField()){
// 上传文件路径和文件、扩展名。
StringsourcePath = fi.getName();
String[]sourcePaths
= sourcePath.split( " //// " );
// 获取真实文件名
StringfileName = sourcePaths[sourcePaths.length - 1 ];
// 创建一个待写文件
FileuploadedFile = new File( new URI(url.toString() + fileName));
// 写入
fi.write(uploadedFile);
out.println(fileName
+ " 上传成功。 " );
}
}
}
catch (Exceptione){
out.println(
" 上传失败,请检查上传文件大小是否超过1兆,并保证在上传时该文件没有被其他程序占用。 " );
out.println(
" <br>原因: " + e.toString());
e.printStackTrace();
}
}
out.println(
" </body> " );
out.println(
" </html> " );
out.flush();
out.close();
}

/**
*Initializationoftheservlet.
*
*
@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{

/**
*Constructoroftheobject.
*/
public UploadServlet(){
super ();
}

/**
*Destructionoftheservlet.
*/
public void destroy(){
super .destroy();
}

public void doGet(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
}

/**
*上传文件
*
*
@param request
*
@param response
*
@throws ServletException
*
@throws IOException
*/
public void doPost(HttpServletRequestrequest,HttpServletResponseresponse)
throws ServletException,IOException{
response.setContentType(
" text/html " );
response.setCharacterEncoding(
" gbk " );
PrintWriterout
= response.getWriter();
out.println(
" <html> " );
out.println(
" <head><title>提示</title></head> " );
out.println(
" <body> " );
// 声明文件域
FileItemfileItem = null ;
// 从HTTPservlet获取fileupload组件需要的内容
RequestContextrequestContext = new ServletRequestContext(request);
// 判断是否包含multipart内容,如果不包含,则不进行任何处理。
if (ServletFileUpload.isMultipartContent(requestContext)){
// 创建基于磁盘的文件工厂
DiskFileItemFactoryfactory = new DiskFileItemFactory();
// 设置直接存储文件的极限大小,一旦超过则写入临时文件以节约内存。默认为1024字节
factory.setSizeThreshold( 1024 * 1024 );
// 创建上传处理器,可以处理从单个HTML上传的多个上传文件。
ServletFileUploadupload = new ServletFileUpload(factory);
// 最大允许上传的文件大小
upload.setSizeMax( 1024 * 1024 );
try {
// 处理上传
Listitems = null ;
items
= upload.parseRequest(requestContext);
// 由于提交了表单字段信息,需要进行循环区分。
for ( int i = 0 ;i < items.size();i ++ ){
FileItemfi
= (FileItem)items.get(i);
// 如果不是表单内容,取出multipart。
if ( ! fi.isFormField()){
fileItem
= fi;
// 一次只上传单个文件
break ;
}
}
out.println(parseExcel(fileItem));
}
catch (Exceptione){
out.println(
" 上传失败!请检查上传的文件是否为excel格式、信息是否完整完整、且大小是否超过1兆。 " );
out.println(
" <br>原因: " + e.toString());
e.printStackTrace();
}
}
out.println(
" </body> " );
out.println(
" </html> " );
out.flush();
out.close();
}

/**
*分析excel文件
*
*
@param FileItemfi文件域
*
@return String
*
@throws Exception
*/
private StringparseExcel(FileItemfi) throws Exception{
// 声明Workbook
Workbookworkbook = null ;
try {
workbook
= Workbook.getWorkbook(fi.getInputStream());
Sheetsheet
= workbook.getSheet( 0 );
// 总行数
int count = sheet.getRows();
// 取出标题
Stringa1 = sheet.getCell( 0 , 0 ).getContents();
Stringa2
= sheet.getCell( 1 , 0 ).getContents();
Stringa3
= sheet.getCell( 2 , 0 ).getContents();
Stringa4
= sheet.getCell( 3 , 0 ).getContents();
Stringa5
= 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 (Exceptione){
throw e;
}
finally {
if (workbook != null ){
workbook.close();
}
}
}

/**
*Initializationoftheservlet.
*
*
@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 " );
Stringfilename
= new String( " 供应商报价清单.xls " .getBytes( " GBK " ), " ISO_8859_1 " );
response.setHeader(
" Content-Disposition " , " attachment;filename= " + filename);

// 虚拟数据
StringmaterialName = " 马桶 " ; // 材料名
Stringsize = " 200×300 " ; // 规格
Stringunit = " " ; // 单位
Stringqty = " 2 " ; // 数量
Stringband = " 不知道牌子 " ; // 材料品牌
Stringcompany = " 成都某厂 " ; // 厂家名
Stringmemo = " 质量可靠 " ; // 备注
Stringprice = " 20.30 " ; // 价格
StringrepDate = " 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);
}

// 输出流
ByteArrayOutputStreambaos = new ByteArrayOutputStream();
// 构造工作区
WritableWorkbookworkbook = Workbook.createWorkbook(baos);
// 构造sheet
WritableSheetsheet = workbook.createSheet( " 报价清单 " , 0 );
// 构造粗标题字体
WritableFontblodFont = new WritableFont(WritableFont.TAHOMA, 10 ,WritableFont.BOLD, false );
WritableCellFormatblodFormat
= new WritableCellFormat(blodFont);
Labellabel
= 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();

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

生成 excel 的样子是这样的:
writeexcel.jpg

请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处: http://www.blogjava.net/rosen


<!--新Google 468*60横幅广告开始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; /* 468x60, 创建于 08-8-6 */ google_ad_slot = "7368701459"; google_ad_width = 468; google_ad_height = 60; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--新Google 468*60横幅广告结束-->

<!--新Google 468x15 横链接单元开始--><script type="text/javascript"><!-- google_ad_client = "pub-7343546549496470"; /* 468x15 横链接单元 */ google_ad_slot = "5785741422"; google_ad_width = 468; google_ad_height = 15; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script><!--新Google 468x15 横链接单元结束-->

<!-- Google Reader shared发布代码开始 --><script type="text/javascript" src="http://www.google.com/reader/ui/publisher.js"></script><script type="text/javascript" src="http://www.google.com/reader/public/javascript/user/00697638153916680411/state/com.google/broadcast?n=5&amp;callback=GRC_p(%7Bc%3A%22green%22%2Ct%3A%22%5Cu8FD9%5Cu4E9B%5Cu6587%5Cu7AE0%5Cu4E5F%5Cu503C%5Cu5F97%5Cu4E00%5Cu770B%22%2Cs%3A%22false%22%7D)%3Bnew%20GRC"></script><!-- Google Reader shared发布代码结束 -->

你可能感兴趣的:(fileupload)