标签:
知识点:
批量导入(ocupload插件,pinyin4J
/POI解析Excel(apache POI)
/区域分页查询
/Combobox下拉框
/分区组合条件分页查询(ajax)
/分区数据导出(Excel下载)
*Ajax不支持文件上传。
*上传并且不刷新上传页面原理:
Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象
<form target="myIframe" action="abc" method="post" enctype="multipart/form-data"> <input type="file" name="myFile"> <input type="submit" value="上传"> </form> <iframe width="0" height="0" frameborder="0" name="myIframe"></iframe>
*选择上传文件后自动上传(无上传按钮)原理:
文件输入框onchange事件 内容一变化就自动提交
将js文件复制到项目中
jquery.ocupload-1.1.2.js
ocupload jquery 的应用代码
$(function () { $(".uploadfile").upload({ action: 'CourseXMLFileUploadHander.ashx', name: 'xml', params: { 'type': 'uploadCourseXMLFile', 'rand': Math.random() }, onSelect: function (self, element) { this.autoSubmit = false; var re = new RegExp("(xml){1}quot;, "i"); if (!re.test(this.filename())) { alert("Only xml file can be uploaded"); } else { this.submit(); } }, onSubmit: function (self, element) { $('.uploadfile').hide(); $('#ajax_update').parent().show(); //alert('Uploading file...'); }, onComplete: function (data, self, element) { $('#ajax_update').parent().hide(); $('.uploadfile').show(); self.resetInput(); try { var ret = data; if (ret.indexOf("exception") >= 0) { alert('Upload file exception: ' + eval(data)[0].exception); } else { showSuccess('File is successfully Load.'); uploadSuccess(ret); } } catch (err) { alert(data); } } }); });
在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素
简单示例
<body> <input id="but1" type="button" value="上传"> <script type="text/javascript"> $("#but1").upload({ action : 'abc',//form表单提交地址 name : 'myFile' }); </script> </body>
原理:js插件会动态的创建form表单和iframe
1.1 在region.jsp页面应用一键上传插件
引入js文件
<script src="${pageContext.request.contextPath }/js/jquery.ocupload-1.1.2.js" type="text/javascript"></script>
调用插件的upload方法
$(function(){ $("#button-import").upload({ action:'${pageContext.request.contextPath}/regionAction_importXls.action', name:'upload', onComplete: function (data, self, element) { if(data == '1'){ $.messager.alert("提示信息","导入数据成功!","info"); }else{ $.messager.alert("提示信息","导入数据失败!","warning"); } } }); });
@Controller @Scope("prototype") public class RegionAction extends BaseAction<Region> { private File upload;// 用于接收上传的文件 public void setUpload(File upload) { this.upload = upload; } // 导入区域数据 public String importXls() throws FileNotFoundException, IOException { System.out.println(upload); // 加载Excel文件到内存中 HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload)); // 读取第一个Sheet页 HSSFSheet sheet = workbook.getSheetAt(0); List<Region> list = new ArrayList<Region>(); for (Row row : sheet) { // int rowNum = row.getRowNum(); String value1 = row.getCell(0).getStringCellValue();// id String value2 = row.getCell(1).getStringCellValue();// provice String value3 = row.getCell(2).getStringCellValue();// city String value4 = row.getCell(3).getStringCellValue();// district String value5 = row.getCell(4).getStringCellValue();// postcode Region region = new Region(value1, value2, value3, value4, value5); // 简码 String shortcode = StringUtils.join( PinYin4jUtils.getHeadByString(value2 + value3), ""); // 城市编码 String citycode = PinYin4jUtils.hanziToPinyin(value3, ""); region.setShortcode(shortcode); region.setCitycode(citycode); list.add(region); } String f = "1"; try { regionService.saveBatch(list); } catch (Exception e) { f = "0"; } ServletActionContext.getResponse().setContentType( "text/html;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(f); return NONE; }
配置struts.xml
略
*重复导入时出现主键冲突:
Duplicate entry ......
解决方法:使用saveOrUpdate
/** * 测试POI解析Excel文件 */ public class POITest { @Test public void test1() throws FileNotFoundException, IOException { HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File( "d:\\abc.xls"))); HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页 for (Row row : sheet) {//循环读取每一行 String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容 String v2 = row.getCell(1).getStringCellValue(); String v3 = row.getCell(2).getStringCellValue(); String v4 = row.getCell(3).getStringCellValue(); String v5 = row.getCell(4).getStringCellValue(); System.out.println(v1 + " " + v2 + " " +v3 + " " + v4 + " " + v5); } } }
@Test public void test1() { String city = "北京市"; String province = "河北省"; String city2 = "石家庄市"; String district = "长安区"; // 城市编码 北京市-----》beijing String str1 = PinYin4jUtils.hanziToPinyin( city.substring(0, city.length() - 1), ""); System.out.println(str1); String info = province.substring(0, province.length() - 1) + city2.substring(0, city2.length() - 1) + district.substring(0, district.length() - 1); // 简码河北省石家庄市长安区-----》hbsjzca String[] strings = PinYin4jUtils.getHeadByString(info); String join = StringUtils.join(strings, ""); System.out.println(join); } }
utils工具类
package cn.itcast.bos.utils; import java.util.Arrays; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; public class PinYin4jUtils { /** * 将字符串转换成拼音数组 * * @param src * @return */ public static String[] stringToPinyin(String src) { return stringToPinyin(src, false, null); } /** * 将字符串转换成拼音数组 * * @param src * @return */ public static String[] stringToPinyin(String src, String separator) { return stringToPinyin(src, true, separator); } /** * 将字符串转换成拼音数组 * * @param src * @param isPolyphone * 是否查出多音字的所有拼音 * @param separator * 多音字拼音之间的分隔符 * @return */ public static String[] stringToPinyin(String src, boolean isPolyphone, String separator) { // 判断字符串是否为空 if ("".equals(src) || null == src) { return null; } char[] srcChar = src.toCharArray(); int srcCount = srcChar.length; String[] srcStr = new String[srcCount]; for (int i = 0; i < srcCount; i++) { srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator); } return srcStr; } /** * 将单个字符转换成拼音 * * @param src * @return */ public static String charToPinyin(char src, boolean isPolyphone, String separator) { // 创建汉语拼音处理类 HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); // 输出设置,大小写,音标方式 defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); StringBuffer tempPinying = new StringBuffer(); // 如果是中文 if (src > 128) { try { // 转换得出结果 String[] strs = PinyinHelper.toHanyuPinyinStringArray(src, defaultFormat); // 是否查出多音字,默认是查出多音字的第一个字符 if (isPolyphone && null != separator) { for (int i = 0; i < strs.length; i++) { tempPinying.append(strs[i]); if (strs.length != (i + 1)) { // 多音字之间用特殊符号间隔起来 tempPinying.append(separator); } } } else { tempPinying.append(strs[0]); } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { tempPinying.append(src); } return tempPinying.toString(); } public static String hanziToPinyin(String hanzi) { return hanziToPinyin(hanzi, " "); } /** * 将汉字转换成拼音 * * @param hanzi * @param separator * @return */ public static String hanziToPinyin(String hanzi, String separator) { // 创建汉语拼音处理类 HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); // 输出设置,大小写,音标方式 defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); String pinyingStr = ""; try { pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat, separator); } catch (BadHanyuPinyinOutputFormatCombination e) { // TODO Auto-generated catch block e.printStackTrace(); } return pinyingStr; } /** * 将字符串数组转换成字符串 * * @param str * @param separator * 各个字符串之间的分隔符 * @return */ public static String stringArrayToString(String[] str, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < str.length; i++) { sb.append(str[i]); if (str.length != (i + 1)) { sb.append(separator); } } return sb.toString(); } /** * 简单的将各个字符数组之间连接起来 * * @param str * @return */ public static String stringArrayToString(String[] str) { return stringArrayToString(str, ""); } /** * 将字符数组转换成字符串 * * @param str * @param separator * 各个字符串之间的分隔符 * @return */ public static String charArrayToString(char[] ch, String separator) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < ch.length; i++) { sb.append(ch[i]); if (ch.length != (i + 1)) { sb.append(separator); } } return sb.toString(); } /** * 将字符数组转换成字符串 * * @param str * @return */ public static String charArrayToString(char[] ch) { return charArrayToString(ch, " "); } /** * 取汉字的首字母 * * @param src * @param isCapital * 是否是大写 * @return */ public static char[] getHeadByChar(char src, boolean isCapital) { // 如果不是汉字直接返回 if (src <= 128) { return new char[] { src }; } // 获取所有的拼音 String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src); // 创建返回对象 int polyphoneSize = pinyingStr.length; char[] headChars = new char[polyphoneSize]; int i = 0; // 截取首字符 for (String s : pinyingStr) { char headChar = s.charAt(0); // 首字母是否大写,默认是小写 if (isCapital) { headChars[i] = Character.toUpperCase(headChar); } else { headChars[i] = headChar; } i++; } return headChars; } /** * 取汉字的首字母(默认是大写) * * @param src * @return */ public static char[] getHeadByChar(char src) { return getHeadByChar(src, true); } /** * 查找字符串首字母 * * @param src * @return */ public static String[] getHeadByString(String src) { return getHeadByString(src, true); } /** * 查找字符串首字母 * * @param src * @param isCapital * 是否大写 * @return */ public static String[] getHeadByString(String src, boolean isCapital) { return getHeadByString(src, isCapital, null); } /** * 查找字符串首字母 * * @param src * @param isCapital * 是否大写 * @param separator * 分隔符 * @return */ public static String[] getHeadByString(String src, boolean isCapital, String separator) { char[] chars = src.toCharArray(); String[] headString = new String[chars.length]; int i = 0; for (char ch : chars) { char[] chs = getHeadByChar(ch, isCapital); StringBuffer sb = new StringBuffer(); if (null != separator) { int j = 1; for (char ch1 : chs) { sb.append(ch1); if (j != chs.length) { sb.append(separator); } j++; } } else { sb.append(chs[0]); } headString[i] = sb.toString(); i++; } return headString; } public static void main(String[] args) { // pin4j 简码 和 城市编码 String s1 = "中华人民共和国"; String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母 System.out.println(Arrays.toString(headArray)); String s2 ="长城" ; System.out.println(Arrays.toString(stringToPinyin(s2,true,","))); String s3 ="长"; System.out.println(Arrays.toString(stringToPinyin(s3,true,","))); } }
修改region.jsp页面中datagrid的url地址
在RegionAction中提供分页查询方法pageQuery
与上一天的代码重复需要提取到baseAction
在BaseAction中提取PageBean和DetachedCriteria对象
protected PageBean pageBean = new PageBean(); // 离线条件查询对象,用于包装查询条件 DetachedCriteria detachedCriteria = null;
在BaseAction中提供setPage和setRows方法
把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中
public void setPage(int page) { pageBean.setCurrentPage(page);// 当前页码 } public void setRows(int rows) { pageBean.setPageSize(rows);// 每页显示记录数 }
在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean
构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中
public BaseAction() { // 获得父类(BaseAction) 类型 ParameterizedType superclass = (ParameterizedType) this.getClass() .getGenericSuperclass(); // 获得父类上的泛型数组 Type[] typeArguments = superclass.getActualTypeArguments(); // 获得实体类型 Class<T> domainClass = (Class<T>) typeArguments[0]; // 获得实体类型后创建离线条件查询对象 detachedCriteria = DetachedCriteria.forClass(domainClass); pageBean.setDetachedCriteria(detachedCriteria); try { model = domainClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
在BaseAction中抽取方法writePageBean2Json和writeListBean2Json
/** * 将PageBean序列化为json返回 */ public void writePageBean2Json(PageBean pageBean, String[] excludes) { // 使用jsonlib将PageBean对象序列化为json数据 JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(excludes); String json = JSONObject.fromObject(pageBean, jsonConfig).toString(); ServletActionContext.getResponse().setContentType( "text/json;charset=UTF-8"); try { ServletActionContext.getResponse().getWriter().print(json); } catch (IOException e) { e.printStackTrace(); } } /** * 将List序列化为json返回 */ public void writeListBean2Json(List list, String[] excludes) { // 使用jsonlib将PageBean对象序列化为json数据 JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(excludes); String json = JSONArray.fromObject(list, jsonConfig).toString(); ServletActionContext.getResponse().setContentType( "text/json;charset=UTF-8"); try { ServletActionContext.getResponse().getWriter().print(json); } catch (IOException e) { e.printStackTrace(); } }
在RegionAction中的分页查询
分页查询代码简化为3条
/** * 分页查询方法 * @throws IOException */ public String pageQuery() throws IOException{ regionService.pageQuery(pageBean); this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"}); return NONE; }
方式一:给静态的select标签应用
方式二:使用input标签通过url动态获取数据(json)
textField:为"option"下拉显示的内容
valueField::为最终提交的value值
<body> <!-- 方式一 --> <select class="easyui-combobox"> <option value="1">河北省石家庄市桥西区</option> <option value="2">河北省石家庄市桥东区</option> <option value="3">河北省石家庄市长安区</option> </select> <!-- 方式二 --> <input data-options="url:'${pageContext.request.contextPath }/json/data.json', textField:'name',valueField:'id'" type="text" class="easyui-combobox"/> </body>
subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)
及添加分区功能
第一步:修改subarea.jsp页面中combobox的url地址
mode属性
定义了当文本改变时如何读取列表数据。设置为‘remote‘时,下拉列表框将会从服务器加载数据。
当设置为“remote”模式时,用户输入将被发送到名为‘q‘的HTTP请求参数到服务器检索新数据。
<td> <input class="easyui-combobox" name="region.id" data-options="mode:'remote',valueField:'id',textField:'name', url:'${pageContext.request.contextPath }/regionAction_list.action'" /> </td>
对应分区类也应增加与下拉栏textField对应的name属性(省市区)
private String id;//编号 private String province;//省 private String city;//市 private String district;//区 private String postcode;//邮编 private String shortcode;//简码 private String citycode;//城市编码 private Set subareas = new HashSet(0);//区域对应的多个分区 public String getName(){ return province + city + district; }
第二步:在RegionAction中提供list方法查询区域数据
private String q;//模糊查询参数 public void setQ(String q) { this.q = q; } /** * 查询所有区域返回json */ public String list(){ List<Region> list = null; if(StringUtils.isNotBlank(q)){ //根据q进行模糊查询 list = regionService.findByQ(q.trim()); }else{ //查询所有 list = regionService.findAll(); } String[] excludes = new String[]{"subareas"}; this.writeListBean2Json(list, excludes); return NONE; }
Service中:
@Override public List<Region> findByQ(String q) { return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%"); }baseIDaompl命名查询
@Override public List<T> findByNameQuery(String hqlName, Object... params) { List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params); return findByNamedQuery; }
对应*hbm.xml提供query hql语句
注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行
<query name="findByQ"> FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ? </query>
第三步:为保存按钮绑定事件
<a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a> <script type="text/javascript"> $(function(){ //为保存按钮绑定事件 $("#save").click(function(){ var v = $("#addForm").form("validate"); if(v){ $("#addForm").submit(); } }); }); </script><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
第四步:创建一个SubareaAction,提供add方法用于添加分区
略
基于datagrid的load方法实现组合条件分页查询
*带关联查询的分页查询转换json会出错
freemarker.template.TemplateModelException:
Method public java.lang.Stringorg.apache.commons.lang.exception
.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:
java.lang.reflect.InvocationTargetException
原因:关联对象延迟加载是代理对象无法转换成json数据
解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题
<many-to-one name="region" class="cn.feibai.bos.domain.Region" fetch="select" lazy="false"> <column name="region_id" length="32" /> </many-to-one>
第一步:提供组合条件查询窗口
第二步:提供一个工具方法,将form表单中的输入项转为json数据,提交参数
$.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; };
第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数
目的:这样发起的查询是ajax请求,条件参数会缓存在页面.
ajax没有全部刷新页面所以对应分页查询的条件也不会丢失
方法:load
参数:param
详情:
加载和显示第一页的所有行。如果指定了‘param‘,它将取代‘queryParams‘属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。
<!-- 查询分区 --> <script type="text/javascript"> //为查询按钮绑定事件 $(function(){ $.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; }; $("#btn").click(function(){ //获取查询条件---一次获取所有的查询条件,将查询条件封装成json数据 var params = $("#searchForm").serializeJson(); //重新发起一次ajax请求,提交参数 $("#grid").datagrid("load",params); //关闭查询窗口 $("#searchWindow").window("close"); }); }); </script>
第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑
Restrictions API
/** * 分页组合条件查询 */ public String pageQuery() { DetachedCriteria subareaDC = pageBean.getDetachedCriteria(); // 从模型对象中获取提交的查询参数 String addresskey = model.getAddresskey();// 关键字 // 单表查询 if (StringUtils.isNotBlank(addresskey)) { // 添加查询条件,根据关键字进行模糊查询 subareaDC.add(Restrictions.like("addresskey", "%" + addresskey.trim() + "%")); } Region region = model.getRegion(); // 多表查询 if (region != null) { String province = region.getProvince(); String city = region.getCity(); String district = region.getDistrict(); DetachedCriteria regionDC = subareaDC.createCriteria("region"); if (StringUtils.isNotBlank(province)) { // 添加查询条件,根据省进行模糊查询 regionDC.add(Restrictions .like("province", "%" + province + "%")); } if (StringUtils.isNotBlank(city)) { // 添加查询条件,根据省进行模糊查询 regionDC.add(Restrictions.like("city", "%" + city + "%")); } if (StringUtils.isNotBlank(district)) { // 添加查询条件,根据省进行模糊查询 regionDC.add(Restrictions .like("district", "%" + district + "%")); } } subareaService.pageQuery(pageBean); String[] excludes = new String[] { "decidedzone", "subareas" }; this.writePageBean2Json(pageBean, excludes); return NONE; }
第一步:修改subarea.jsp页面中导出按钮的事件
function doExport(){ //发起请求Action,查询所有分区数据,写到Excel文件中并提供下载 window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action"; }
第二步:在Action中提供exportXls方法
两种方法:
方式一:原始手动设置响应下载
文件名乱码工具类
import java.io.IOException; import java.net.URLEncoder; import sun.misc.BASE64Encoder; public class FileUtils { /** * 下载文件时,针对不同浏览器,进行附件名的编码 * * @param filename * 下载文件名 * @param agent * 客户端浏览器 * @return 编码后的下载附件名 * @throws IOException */ public static String encodeDownloadFilename(String filename, String agent) throws IOException { if (agent.contains("Firefox")) { // 火狐浏览器 filename = "=?UTF-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?="; filename = filename.replaceAll("\r\n", ""); } else { // IE及其他浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+"," "); } return filename; } }
/** * 导出分区数据到Excel文件并提供下载 * * @throws IOException */ public String exportXls() throws IOException { List<Subarea> list = subareaService.findAll(); // 使用POI将查询的数据写入Excel文件中 HSSFWorkbook workbook = new HSSFWorkbook(); // 在工作表中创建一个sheet页 HSSFSheet sheet = workbook.createSheet("分区数据"); // 创建标题行 HSSFRow headRow = sheet.createRow(0); // 创建单元格 headRow.createCell(0).setCellValue("分区编号"); headRow.createCell(1).setCellValue("关键字"); headRow.createCell(2).setCellValue("地址"); headRow.createCell(3).setCellValue("省市区"); for (Subarea subarea : list) { // 创建数据行 HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1); String id = subarea.getId(); String addresskey = subarea.getAddresskey(); String position = subarea.getPosition(); Region region = subarea.getRegion(); dataRow.createCell(0).setCellValue(id); dataRow.createCell(1).setCellValue(addresskey); dataRow.createCell(2).setCellValue(position); if (region != null) { String province = region.getProvince(); String city = region.getCity(); String district = region.getDistrict(); String info = province + city + district; dataRow.createCell(3).setCellValue(info); } } String filename = "分区数据.xls"; String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型 filename = FileUtils.encodeDownloadFilename(filename, agent ); //根据文件名称动态获得类型 String contentType = ServletActionContext.getServletContext() .getMimeType(filename); // 通知客户端下载文件的类型 ServletActionContext.getResponse().setContentType(contentType); //指定以附件形式下载,指定文件名称 ServletActionContext.getResponse().setHeader("content-disposition", "attachment;filename=" + filename); // 通过输出流向客户端浏览器写Excel文件 ServletOutputStream out = ServletActionContext.getResponse().getOutputStream(); workbook.write(out); return NONE; } }
方式二:通过struts2的stream结果集下载
思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):
思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.
使用了ByteArrayOutputStream和ByteArrayInputStream类...处理的思想是,将HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流
<pre name="code" class="java"> private InputStream target; public InputStream getTarget() { return target; } //下载文件名,存在中文乱码 private String downloadFileName; public String getDownloadFileName() throws UnsupportedEncodingException { // 处理中文乱码 if(downloadFileName != null){ return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1"); } return downloadFileName; } /** * 下载所有分区信息以xls格式 * @return * @throws IOException */ public String export() throws IOException{ List<Subarea> list=subareaService.findAll(); //把list写入excel文档 HSSFWorkbook book=new HSSFWorkbook(); HSSFSheet sheet = book.createSheet("全部分区详情"); //创建初始标题行 HSSFRow row = sheet.createRow(0); row.createCell(0).setCellValue("分拣编号"); row.createCell(1).setCellValue("省市区"); row.createCell(2).setCellValue("关键字"); row.createCell(3).setCellValue("位置"); //遍历list for (Subarea subarea : list) { HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1); String id = subarea.getId(); String nameInfo = subarea.getRegion().getName(); String addresskey = subarea.getAddresskey(); String position = subarea.getPosition(); createRow.createCell(0).setCellValue(id); createRow.createCell(1).setCellValue(nameInfo); createRow.createCell(2).setCellValue(addresskey); createRow.createCell(3).setCellValue(position); } ByteArrayOutputStream out = new ByteArrayOutputStream(); book.write(out); target = new ByteArrayInputStream(out.toByteArray()); out.close(); downloadFileName="分区详情.xls"; return "download"; }配置文件
<!-- 分区 --> <action name="subareaAction_*" class="subareaAction" method="{1}"> <result name="subareaList">/WEB-INF/pages/base/subarea.jsp</result> <result name="download" type="stream"> <!-- 设置响应头 --> <param name="contentDisposition">attachment;filename=${downloadFileName}</param> <!-- 确定流 --> <param name="inputName">target</param> </result> </action>
框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)
标签:
原文地址:http://blog.csdn.net/opopopwqwqwq/article/details/51626964